dolphindb 0.0.13 → 2.0.500

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/index.d.ts CHANGED
@@ -81,17 +81,24 @@ export interface DdbArrayVectorBlock {
81
81
  export declare type DdbValue = null | boolean | number | [number, number] | bigint | string | string[] | Uint8Array | Int16Array | Int32Array | Float32Array | Float64Array | BigInt64Array | Uint8Array[] | DdbObj[] | DdbFunctionDefValue | DdbSymbolExtendedValue | DdbArrayVectorBlock[];
82
82
  export declare type DdbVectorValue = string | string[] | Uint8Array | Int16Array | Int32Array | Float32Array | Float64Array | BigInt64Array | Uint8Array[] | DdbObj[] | DdbSymbolExtendedValue | DdbArrayVectorBlock[];
83
83
  export declare const nulls: {
84
+ readonly bool: 128;
84
85
  readonly char: "€";
85
86
  readonly int16: -32768;
86
87
  readonly int32: -2147483648;
87
88
  readonly int64: -9223372036854775808n;
89
+ readonly float32: -3.4028234663852886e+38;
90
+ /** -Number.MAX_VALUE */
91
+ readonly double: number;
92
+ readonly bytes16: Uint8Array;
88
93
  };
89
94
  export declare const timezone_offset: number;
90
95
  /** 可以表示所有 DolphinDB 数据库中的数据类型 */
91
96
  export declare class DdbObj<T extends DdbValue = DdbValue> {
92
97
  static dec: TextDecoder;
93
98
  static enc: TextEncoder;
94
- /** 维护已解析的 symbol base,比如流数据中后续的 symbol 向量可能只发送一个 base.id, base.size == 0, 依赖之前发送的 symbol base */
99
+ /** 维护已解析的 symbol base,比如流数据中后续的 symbol 向量可能只发送一个 base.id, base.size == 0, 依赖之前发送的 symbol base ?
100
+ 只是暂存,如果一张表有多个 symbol 列,可能这个 symbol base 会被复用,不同的对象之间 symbol base 一般不复用
101
+ */
95
102
  static symbol_bases: Record<number, string[]>;
96
103
  /** little endian (client) */
97
104
  static le_client: boolean;
@@ -147,57 +154,82 @@ export declare class DdbVoid extends DdbObj<undefined> {
147
154
  constructor();
148
155
  }
149
156
  export declare class DdbBool extends DdbObj<boolean> {
150
- constructor(value: boolean);
157
+ constructor(value: boolean | null);
151
158
  }
152
159
  export declare class DdbChar extends DdbObj<string> {
153
- constructor(value: string);
160
+ constructor(value: string | null);
154
161
  }
155
162
  export declare class DdbInt extends DdbObj<number> {
156
- constructor(value: number);
163
+ constructor(value: number | null);
157
164
  }
158
165
  export declare class DdbString extends DdbObj<string> {
159
166
  constructor(value: string);
160
167
  }
161
168
  export declare class DdbLong extends DdbObj<bigint> {
162
- constructor(value: bigint);
169
+ constructor(value: bigint | null);
163
170
  }
164
171
  export declare class DdbDouble extends DdbObj<number> {
165
- constructor(value: number);
172
+ constructor(value: number | null);
166
173
  }
167
174
  export declare class DdbDateTime extends DdbObj<number> {
168
- constructor(value: number);
175
+ constructor(value: number | null);
169
176
  }
170
177
  export declare class DdbTimeStamp extends DdbObj<bigint> {
171
- constructor(value: bigint);
178
+ constructor(value: bigint | null);
172
179
  }
173
180
  export declare class DdbNanoTimeStamp extends DdbObj<bigint> {
174
- constructor(value: bigint);
181
+ constructor(value: bigint | null);
175
182
  }
176
183
  export declare class DdbVectorInt extends DdbObj<Int32Array> {
177
- constructor(value: number[], name?: string);
184
+ constructor(value: (number | null)[] | Int32Array, name?: string);
178
185
  }
179
186
  export declare class DdbVectorString extends DdbObj<string[]> {
180
187
  constructor(value: string[], name?: string);
181
188
  }
182
189
  export declare class DdbVectorDouble extends DdbObj<Float64Array> {
183
- constructor(value: number[], name?: string);
190
+ constructor(value: (number | null)[] | Float64Array, name?: string);
184
191
  }
185
192
  export declare class DdbVectorAny extends DdbObj {
186
193
  constructor(value: DdbObj<DdbValue>[], name?: string);
187
194
  }
195
+ export declare class DdbVectorSymbol extends DdbObj<DdbSymbolExtendedValue> {
196
+ constructor(value: string[], name?: string);
197
+ }
188
198
  export declare class DdbPair extends DdbObj<Int32Array> {
189
- constructor(l: number, r?: number);
199
+ constructor(l: number | null, r?: number | null);
190
200
  }
191
201
  export declare class DdbFunction extends DdbObj<DdbFunctionDefValue> {
192
202
  constructor(name: string, type: DdbFunctionType);
193
203
  }
194
204
  export declare function date2str(date: number, format?: string): string;
195
205
  export declare function datetime2str(datetime: number, format?: string): string;
196
- export declare function timestamp2str(timestamp: bigint): string;
206
+ /** format timestamp (bigint) to string
207
+ - timestamp: bigint value
208
+ - format?:
209
+ format string, default to `YYYY.MM.DD HH:mm:ss.SSS`
210
+ https://day.js.org/docs/en/parse/string-format#list-of-all-available-parsing-tokens
211
+ */
212
+ export declare function timestamp2str(timestamp: bigint, format?: string): string;
213
+ /** parse timestamp string to bigint value
214
+ - str: timestamp string, If it is an empty string, it will return the corresponding empty value (nulls.int64)
215
+ - format?:
216
+ The format string corresponding to the incoming string, the default is `YYYY.MM.DD HH:mm:ss.SSS`
217
+ https://day.js.org/docs/en/parse/string-format#list-of-all-available-parsing-tokens
218
+ */
219
+ export declare function str2timestamp(str: string, format?: string): bigint;
220
+ /** format nanotimestamp value (bigint) to string
221
+ - nanotimestamp: bigint value
222
+ - format?:
223
+ format string, default is `YYYY.MM.DD HH:mm:ss.SSSSSSSSS`
224
+ Seconds are in the format ss (must be included); nanoseconds are in the format SSSSSSSSS (must be included)
225
+ https://day.js.org/docs/en/parse/string-format#list-of-all-available-parsing-tokens
226
+ */
197
227
  export declare function nanotimestamp2str(nanotimestamp: bigint, format?: string): string;
198
228
  /** parse nano timestamp string to bigint value
199
- - str: nano timestamp string, 如果为空字符串会返回对应的空值 (nulls.int64)
200
- - format?: 对应传入字符串的到秒之前 (包括) 的格式串,默认是 `YYYY.MM.DD HH:mm:ss`
229
+ - str: nano timestamp string, If it is an empty string, it will return the corresponding empty value (nulls.int64)
230
+ - format?:
231
+ The format string corresponding to the incoming string, the default is `YYYY.MM.DD HH:mm:ss.SSSSSSSSS`
232
+ Seconds are in the format ss (must be included); nanoseconds are in the format SSSSSSSSS (must be included)
201
233
  https://day.js.org/docs/en/parse/string-format#list-of-all-available-parsing-tokens
202
234
  */
203
235
  export declare function str2nanotimestamp(str: string, format?: string): bigint;
@@ -226,6 +258,7 @@ export declare class DDB {
226
258
  presolver(buf: Uint8Array): void;
227
259
  prejector(error: Error): void;
228
260
  presult: Promise<Uint8Array>;
261
+ get connected(): boolean;
229
262
  /**
230
263
  Initialize an instance of DolphinDB Client using the WebSocket URL
231
264
  (without establishing an actual network connection)
@@ -326,7 +359,7 @@ export declare class DDB {
326
359
  };
327
360
  /** 自动转换 js string, boolean 为 DdbObj */
328
361
  to_ddbobj(value: DdbObj | string | boolean): DdbObj;
329
- /** 转换 js 数组为 DdbObj[] (in place, 会修改原数组) */
362
+ /** 转换 js 数组为 DdbObj[] */
330
363
  to_ddbobjs(values: any[]): DdbObj<DdbValue>[];
331
364
  }
332
365
  export default DDB;
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DDB = exports.str2nanotimestamp = exports.nanotimestamp2str = exports.timestamp2str = exports.datetime2str = exports.date2str = exports.DdbFunction = exports.DdbPair = exports.DdbVectorAny = exports.DdbVectorDouble = exports.DdbVectorString = exports.DdbVectorInt = exports.DdbNanoTimeStamp = exports.DdbTimeStamp = exports.DdbDateTime = exports.DdbDouble = exports.DdbLong = exports.DdbString = exports.DdbInt = exports.DdbChar = exports.DdbBool = exports.DdbVoid = exports.DdbObj = exports.timezone_offset = exports.nulls = exports.DdbFunctionType = exports.ddb_sizes = exports.DdbType = exports.DdbForm = void 0;
3
+ exports.DDB = exports.str2nanotimestamp = exports.nanotimestamp2str = exports.str2timestamp = exports.timestamp2str = exports.datetime2str = exports.date2str = exports.DdbFunction = exports.DdbPair = exports.DdbVectorSymbol = exports.DdbVectorAny = exports.DdbVectorDouble = exports.DdbVectorString = exports.DdbVectorInt = exports.DdbNanoTimeStamp = exports.DdbTimeStamp = exports.DdbDateTime = exports.DdbDouble = exports.DdbLong = exports.DdbString = exports.DdbInt = exports.DdbChar = exports.DdbBool = exports.DdbVoid = exports.DdbObj = exports.timezone_offset = exports.nulls = exports.DdbFunctionType = exports.ddb_sizes = exports.DdbType = exports.DdbForm = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const ws_1 = require("ws");
6
6
  const dayjs_1 = tslib_1.__importDefault(require("dayjs"));
@@ -109,10 +109,15 @@ var DdbFunctionType;
109
109
  DdbFunctionType[DdbFunctionType["JitPartialFunc"] = 8] = "JitPartialFunc";
110
110
  })(DdbFunctionType = exports.DdbFunctionType || (exports.DdbFunctionType = {}));
111
111
  exports.nulls = {
112
+ bool: 0x80,
112
113
  char: '\x80',
113
114
  int16: -32768,
114
115
  int32: -2147483648,
115
- int64: -0x8000000000000000n, // -922_3372_0368_5477_5808
116
+ int64: -0x8000000000000000n,
117
+ float32: -3.4028234663852886e+38,
118
+ /** -Number.MAX_VALUE */
119
+ double: -Number.MAX_VALUE,
120
+ bytes16: Uint8Array.from(new Array(16).fill(0))
116
121
  };
117
122
  exports.timezone_offset = 1000 * 60 * new Date().getTimezoneOffset();
118
123
  /** 可以表示所有 DolphinDB 数据库中的数据类型 */
@@ -129,7 +134,7 @@ class DdbObj {
129
134
  form: DdbForm.scalar,
130
135
  type: DdbType.void,
131
136
  length: 0,
132
- value: undefined
137
+ value: null
133
138
  });
134
139
  const type = buf[0];
135
140
  const form = buf[1];
@@ -278,13 +283,18 @@ class DdbObj {
278
283
  switch (type) {
279
284
  case DdbType.void:
280
285
  return [1, null];
281
- case DdbType.bool:
282
- return [1, Boolean(buf[0])];
283
- case DdbType.char:
284
- return [1, String.fromCharCode(buf[0])];
286
+ case DdbType.bool: {
287
+ const value = buf[0];
288
+ return [1, value === exports.nulls.bool ? null : Boolean(value)];
289
+ }
290
+ case DdbType.char: {
291
+ const value = String.fromCharCode(buf[0]);
292
+ return [1, value === exports.nulls.char ? null : value];
293
+ }
285
294
  case DdbType.short: {
286
295
  const dv = new DataView(buf.buffer, buf.byteOffset);
287
- return [2, dv.getInt16(0, le)];
296
+ const value = dv.getInt16(0, le);
297
+ return [2, value === exports.nulls.int16 ? null : value];
288
298
  }
289
299
  case DdbType.int:
290
300
  // datetime
@@ -296,15 +306,18 @@ class DdbObj {
296
306
  case DdbType.datetime:
297
307
  case DdbType.datehour: {
298
308
  const dv = new DataView(buf.buffer, buf.byteOffset);
299
- return [4, dv.getInt32(0, le)];
309
+ const value = dv.getInt32(0, le);
310
+ return [4, value === exports.nulls.int32 ? null : value];
300
311
  }
301
312
  case DdbType.float: {
302
313
  const dv = new DataView(buf.buffer, buf.byteOffset);
303
- return [4, dv.getFloat32(0, le)];
314
+ const value = dv.getFloat32(0, le);
315
+ return [4, value === exports.nulls.float32 ? null : value];
304
316
  }
305
317
  case DdbType.double: {
306
318
  const dv = new DataView(buf.buffer, buf.byteOffset);
307
- return [8, dv.getFloat64(0, le)];
319
+ const value = dv.getFloat64(0, le);
320
+ return [8, value === exports.nulls.double ? null : value];
308
321
  }
309
322
  case DdbType.long:
310
323
  // timestamp
@@ -312,7 +325,8 @@ class DdbObj {
312
325
  case DdbType.nanotime:
313
326
  case DdbType.nanotimestamp: {
314
327
  const dv = new DataView(buf.buffer, buf.byteOffset);
315
- return [8, dv.getBigInt64(0, le)];
328
+ const value = dv.getBigInt64(0, le);
329
+ return [8, value === exports.nulls.int64 ? null : value];
316
330
  }
317
331
  case DdbType.string:
318
332
  case DdbType.symbol:
@@ -613,11 +627,26 @@ class DdbObj {
613
627
  case DdbType.void:
614
628
  return [Uint8Array.of(1)];
615
629
  case DdbType.bool:
616
- return [Uint8Array.of(Number(value))];
630
+ return [
631
+ Uint8Array.of(value === null ?
632
+ exports.nulls.bool
633
+ :
634
+ Number(value))
635
+ ];
617
636
  case DdbType.char:
618
- return [Uint8Array.of(value.charCodeAt(0))];
637
+ return [
638
+ Uint8Array.of((value === null ?
639
+ exports.nulls.char
640
+ :
641
+ value).charCodeAt(0))
642
+ ];
619
643
  case DdbType.short:
620
- return [Int16Array.of(value)];
644
+ return [
645
+ Int16Array.of(value === null ?
646
+ exports.nulls.int16
647
+ :
648
+ value)
649
+ ];
621
650
  case DdbType.int:
622
651
  // datetime
623
652
  case DdbType.date:
@@ -627,17 +656,37 @@ class DdbObj {
627
656
  case DdbType.second:
628
657
  case DdbType.datetime:
629
658
  case DdbType.datehour:
630
- return [Int32Array.of(value)];
659
+ return [
660
+ Int32Array.of(value === null ?
661
+ exports.nulls.int32
662
+ :
663
+ value)
664
+ ];
631
665
  case DdbType.float:
632
- return [Float32Array.of(value)];
666
+ return [
667
+ Float32Array.of(value === null ?
668
+ exports.nulls.float32
669
+ :
670
+ value)
671
+ ];
633
672
  case DdbType.double:
634
- return [Float64Array.of(value)];
673
+ return [
674
+ Float64Array.of(value === null ?
675
+ exports.nulls.double
676
+ :
677
+ value)
678
+ ];
635
679
  case DdbType.long:
636
680
  // timestamp
637
681
  case DdbType.timestamp:
638
682
  case DdbType.nanotime:
639
683
  case DdbType.nanotimestamp:
640
- return [BigInt64Array.of(this.value)];
684
+ return [
685
+ BigInt64Array.of(value === null ?
686
+ exports.nulls.int64
687
+ :
688
+ value)
689
+ ];
641
690
  case DdbType.string:
642
691
  case DdbType.symbol:
643
692
  case DdbType.code:
@@ -801,7 +850,7 @@ class DdbObj {
801
850
  case DdbType.symbol_extended: {
802
851
  const { base_id, base, data } = value;
803
852
  return [
804
- Uint32Array.of(base_id, base.length),
853
+ Uint32Array.of(base_id || 0, base.length),
805
854
  ...this.pack_vector_body(base, DdbType.string, base.length),
806
855
  data
807
856
  ];
@@ -862,6 +911,11 @@ class DdbObj {
862
911
  case DdbType.ipaddr:
863
912
  row[name] = value.subarray(16 * i, 16 * (i + 1));
864
913
  break;
914
+ case DdbType.symbol_extended: {
915
+ const { base, data } = value;
916
+ row[name] = base[data[i]];
917
+ break;
918
+ }
865
919
  default:
866
920
  row[name] = value[i];
867
921
  }
@@ -883,7 +937,9 @@ class DdbObj {
883
937
  exports.DdbObj = DdbObj;
884
938
  DdbObj.dec = new TextDecoder('utf-8');
885
939
  DdbObj.enc = new TextEncoder();
886
- /** 维护已解析的 symbol base,比如流数据中后续的 symbol 向量可能只发送一个 base.id, base.size == 0, 依赖之前发送的 symbol base */
940
+ /** 维护已解析的 symbol base,比如流数据中后续的 symbol 向量可能只发送一个 base.id, base.size == 0, 依赖之前发送的 symbol base ?
941
+ 只是暂存,如果一张表有多个 symbol 列,可能这个 symbol base 会被复用,不同的对象之间 symbol base 一般不复用
942
+ */
887
943
  DdbObj.symbol_bases = {};
888
944
  /** little endian (client) */
889
945
  DdbObj.le_client = Boolean(new Uint8Array(Uint32Array.of(1).buffer)[0]);
@@ -893,6 +949,7 @@ class DdbVoid extends DdbObj {
893
949
  form: DdbForm.scalar,
894
950
  type: DdbType.void,
895
951
  length: 0,
952
+ value: null,
896
953
  });
897
954
  }
898
955
  }
@@ -925,7 +982,7 @@ class DdbInt extends DdbObj {
925
982
  form: DdbForm.scalar,
926
983
  type: DdbType.int,
927
984
  length: 4,
928
- value
985
+ value,
929
986
  });
930
987
  }
931
988
  }
@@ -1004,7 +1061,13 @@ class DdbVectorInt extends DdbObj {
1004
1061
  length: 0,
1005
1062
  rows: value.length,
1006
1063
  cols: 1,
1007
- value: Int32Array.from(value),
1064
+ value: value instanceof Int32Array ?
1065
+ value
1066
+ :
1067
+ Int32Array.from(value, v => v === null ?
1068
+ exports.nulls.int32
1069
+ :
1070
+ v),
1008
1071
  name,
1009
1072
  });
1010
1073
  }
@@ -1032,7 +1095,13 @@ class DdbVectorDouble extends DdbObj {
1032
1095
  length: 0,
1033
1096
  rows: value.length,
1034
1097
  cols: 1,
1035
- value: Float64Array.from(value),
1098
+ value: value instanceof Float64Array ?
1099
+ value
1100
+ :
1101
+ Float64Array.from(value, v => v === null ?
1102
+ exports.nulls.double
1103
+ :
1104
+ v),
1036
1105
  name,
1037
1106
  });
1038
1107
  }
@@ -1052,15 +1121,46 @@ class DdbVectorAny extends DdbObj {
1052
1121
  }
1053
1122
  }
1054
1123
  exports.DdbVectorAny = DdbVectorAny;
1124
+ class DdbVectorSymbol extends DdbObj {
1125
+ constructor(value, name) {
1126
+ let map = new Map([
1127
+ ['', 0]
1128
+ ]);
1129
+ let data = new Uint32Array(value.length);
1130
+ for (let i = 0; i < value.length; i++) {
1131
+ const x = value[i];
1132
+ let index = map.get(x);
1133
+ if (index === undefined) {
1134
+ index = map.size;
1135
+ map.set(x, index);
1136
+ }
1137
+ data[i] = index;
1138
+ }
1139
+ super({
1140
+ form: DdbForm.vector,
1141
+ type: DdbType.symbol_extended,
1142
+ length: 0,
1143
+ rows: value.length,
1144
+ cols: 1,
1145
+ value: {
1146
+ base: [...map.keys()],
1147
+ base_id: null,
1148
+ data,
1149
+ },
1150
+ name
1151
+ });
1152
+ }
1153
+ }
1154
+ exports.DdbVectorSymbol = DdbVectorSymbol;
1055
1155
  class DdbPair extends DdbObj {
1056
- constructor(l, r = -2147483648) {
1156
+ constructor(l, r = null) {
1057
1157
  super({
1058
1158
  form: DdbForm.pair,
1059
1159
  type: DdbType.int,
1060
1160
  length: 0,
1061
1161
  rows: 2,
1062
1162
  cols: 1,
1063
- value: Int32Array.of(l, r)
1163
+ value: Int32Array.of(l === null ? exports.nulls.int32 : l, r === null ? exports.nulls.int32 : r)
1064
1164
  });
1065
1165
  }
1066
1166
  }
@@ -1090,34 +1190,79 @@ function datetime2str(datetime, format = 'YYYY.MM.DD HH:mm:ss') {
1090
1190
  (0, dayjs_1.default)(exports.timezone_offset + 1000 * datetime).format(format);
1091
1191
  }
1092
1192
  exports.datetime2str = datetime2str;
1093
- function timestamp2str(timestamp) {
1193
+ /** format timestamp (bigint) to string
1194
+ - timestamp: bigint value
1195
+ - format?:
1196
+ format string, default to `YYYY.MM.DD HH:mm:ss.SSS`
1197
+ https://day.js.org/docs/en/parse/string-format#list-of-all-available-parsing-tokens
1198
+ */
1199
+ function timestamp2str(timestamp, format = 'YYYY.MM.DD HH:mm:ss.SSS') {
1094
1200
  return timestamp === exports.nulls.int64 ?
1095
1201
  ''
1096
1202
  :
1097
- (0, dayjs_1.default)(exports.timezone_offset + Number(timestamp)).format('YYYY.MM.DD HH:mm:ss.SSS');
1203
+ (0, dayjs_1.default)(exports.timezone_offset + Number(timestamp)).format(format);
1098
1204
  }
1099
1205
  exports.timestamp2str = timestamp2str;
1100
- function nanotimestamp2str(nanotimestamp, format = 'YYYY.MM.DD HH:mm:ss') {
1101
- return nanotimestamp === exports.nulls.int64 ?
1102
- ''
1103
- :
1104
- (0, dayjs_1.default)(exports.timezone_offset + (Number(nanotimestamp) / 1000000)).format(format) + `.${nanotimestamp % 1000000000n}`;
1206
+ /** parse timestamp string to bigint value
1207
+ - str: timestamp string, If it is an empty string, it will return the corresponding empty value (nulls.int64)
1208
+ - format?:
1209
+ The format string corresponding to the incoming string, the default is `YYYY.MM.DD HH:mm:ss.SSS`
1210
+ https://day.js.org/docs/en/parse/string-format#list-of-all-available-parsing-tokens
1211
+ */
1212
+ function str2timestamp(str, format = 'YYYY.MM.DD HH:mm:ss.SSS') {
1213
+ if (!str)
1214
+ return exports.nulls.int64;
1215
+ if (str.length !== format.length)
1216
+ throw new Error('The length of the timestamp string is not equal to the length of the format string');
1217
+ return BigInt(-exports.timezone_offset +
1218
+ (0, dayjs_1.default)(str, format).valueOf());
1219
+ }
1220
+ exports.str2timestamp = str2timestamp;
1221
+ /** format nanotimestamp value (bigint) to string
1222
+ - nanotimestamp: bigint value
1223
+ - format?:
1224
+ format string, default is `YYYY.MM.DD HH:mm:ss.SSSSSSSSS`
1225
+ Seconds are in the format ss (must be included); nanoseconds are in the format SSSSSSSSS (must be included)
1226
+ https://day.js.org/docs/en/parse/string-format#list-of-all-available-parsing-tokens
1227
+ */
1228
+ function nanotimestamp2str(nanotimestamp, format = 'YYYY.MM.DD HH:mm:ss.SSSSSSSSS') {
1229
+ if (nanotimestamp === exports.nulls.int64)
1230
+ return '';
1231
+ const i_second_start = format.indexOf('ss');
1232
+ if (i_second_start === -1)
1233
+ throw new Error('The format string must contain the format for seconds (ss)');
1234
+ const i_second_end = i_second_start + 2;
1235
+ const i_nanosecond_start = format.indexOf('SSSSSSSSS', i_second_end);
1236
+ if (i_nanosecond_start === -1)
1237
+ throw new Error('The format string must contain the format for nanoseconds (SSSSSSSSS)');
1238
+ return ((0, dayjs_1.default)(exports.timezone_offset + (Number(nanotimestamp) / 1000000)).format(format.slice(0, i_second_end)) +
1239
+ format.slice(i_second_end, i_nanosecond_start) +
1240
+ String(nanotimestamp % 1000000000n));
1105
1241
  }
1106
1242
  exports.nanotimestamp2str = nanotimestamp2str;
1107
1243
  /** parse nano timestamp string to bigint value
1108
- - str: nano timestamp string, 如果为空字符串会返回对应的空值 (nulls.int64)
1109
- - format?: 对应传入字符串的到秒之前 (包括) 的格式串,默认是 `YYYY.MM.DD HH:mm:ss`
1244
+ - str: nano timestamp string, If it is an empty string, it will return the corresponding empty value (nulls.int64)
1245
+ - format?:
1246
+ The format string corresponding to the incoming string, the default is `YYYY.MM.DD HH:mm:ss.SSSSSSSSS`
1247
+ Seconds are in the format ss (must be included); nanoseconds are in the format SSSSSSSSS (must be included)
1110
1248
  https://day.js.org/docs/en/parse/string-format#list-of-all-available-parsing-tokens
1111
1249
  */
1112
- function str2nanotimestamp(str, format = 'YYYY.MM.DD HH:mm:ss') {
1250
+ function str2nanotimestamp(str, format = 'YYYY.MM.DD HH:mm:ss.SSSSSSSSS') {
1113
1251
  if (!str)
1114
1252
  return exports.nulls.int64;
1115
- if (str.length - format.length !== 9)
1116
- throw new Error('nanotimestamp 字符串长度减格式串长度应该等于 9');
1253
+ if (str.length !== format.length)
1254
+ throw new Error('nanotimestamp string length is not equal to format string length');
1255
+ const i_second_start = format.indexOf('ss');
1256
+ if (i_second_start === -1)
1257
+ throw new Error('The format string must contain the format for seconds (ss)');
1258
+ const i_second_end = i_second_start + 2;
1259
+ const i_nanosecond_start = format.indexOf('SSSSSSSSS', i_second_end);
1260
+ if (i_nanosecond_start === -1)
1261
+ throw new Error('Format string must contain nanosecond format (SSSSSSSSS)');
1117
1262
  return (BigInt(-exports.timezone_offset +
1118
- (0, dayjs_1.default)(str.slice(0, format.length), format).valueOf()) * 1000000n
1263
+ (0, dayjs_1.default)(str.slice(0, i_second_end), format.slice(0, i_second_end)).valueOf()) * 1000000n
1119
1264
  +
1120
- BigInt(str.slice(format.length)));
1265
+ BigInt(str.slice(i_nanosecond_start, i_nanosecond_start + 9)));
1121
1266
  }
1122
1267
  exports.str2nanotimestamp = str2nanotimestamp;
1123
1268
  class DDB {
@@ -1151,12 +1296,14 @@ class DDB {
1151
1296
  /** resolver, rejector, promise of last rpc */
1152
1297
  presolver(buf) { }
1153
1298
  prejector(error) { }
1299
+ get connected() {
1300
+ return this.websocket?.readyState === ws_1.WebSocket.OPEN;
1301
+ }
1154
1302
  /** Establish the actual WebSocket connection to the DolphinDB corresponding to the URL */
1155
1303
  async connect({ url = this.url, login = true, username = 'admin', password = '123456', python = false, } = {}) {
1156
1304
  this.url = url;
1157
1305
  this.python = python;
1158
- if (this.websocket?.readyState === ws_1.WebSocket.OPEN)
1159
- this.disconnect();
1306
+ this.disconnect();
1160
1307
  let websocket = new ws_1.WebSocket(url, python ? ['python'] : [], {
1161
1308
  maxPayload: 2 ** 33 // 8 GB
1162
1309
  });
@@ -1212,7 +1359,10 @@ class DDB {
1212
1359
  ' )\n' +
1213
1360
  '}\n', { urgent: true });
1214
1361
  if (login)
1215
- await this.call('login', [username, password], { urgent: true });
1362
+ if (this.python)
1363
+ await this.eval(`login(${username.quote('double')}, ${password.quote('double')})`, { urgent: true });
1364
+ else
1365
+ await this.call('login', [username, password], { urgent: true });
1216
1366
  }
1217
1367
  get_rpc_options({ urgent = false, secondary = false, async: _async = false, pickle = false, clear = false, api = false, compress = false, cancellable = true, priority = urgent ? 8 : 4, parallelism = 8, root_id = '', limit, } = {}) {
1218
1368
  let flag = 0;
@@ -1246,7 +1396,11 @@ class DDB {
1246
1396
  return `/ ${options.join('_')}`;
1247
1397
  }
1248
1398
  disconnect() {
1249
- this.websocket?.close(1000);
1399
+ if (this.connected)
1400
+ this.websocket.close(1000);
1401
+ this.presolver = buf => { };
1402
+ this.prejector = error => { };
1403
+ this.presult = Promise.resolve(null);
1250
1404
  }
1251
1405
  /** rpc through websocket (function/script/variable command)
1252
1406
  - type: API 类型: 'script' | 'function' | 'variable'
@@ -1257,7 +1411,7 @@ class DDB {
1257
1411
  async rpc(type, { script, func, args = [], vars = [], urgent, }) {
1258
1412
  if (!this.websocket)
1259
1413
  await this.connect();
1260
- if (this.websocket.readyState !== ws_1.WebSocket.OPEN)
1414
+ if (!this.connected)
1261
1415
  throw new Error(`${this.url} is already disconnected`);
1262
1416
  // 临界区:保证多个 rpc 并发时形成 promise 链
1263
1417
  // ddb 世界观:需要等待上一个 rpc 结果从 server 返回之后才能发起下一个调用
@@ -1280,7 +1434,7 @@ class DDB {
1280
1434
  // 临界区结束,只有一个 rpc 请求可以写 WebSocket
1281
1435
  if (urgent && type !== 'script' && type !== 'function')
1282
1436
  throw new Error('urgent 只适用于 script 和 funciton');
1283
- this.to_ddbobjs(args);
1437
+ args = this.to_ddbobjs(args);
1284
1438
  const command = this.enc.encode((() => {
1285
1439
  switch (type) {
1286
1440
  case 'function':
@@ -1426,11 +1580,9 @@ class DDB {
1426
1580
  throw new Error(`不能自动转换 ${type} 至 DdbObj`);
1427
1581
  }
1428
1582
  }
1429
- /** 转换 js 数组为 DdbObj[] (in place, 会修改原数组) */
1583
+ /** 转换 js 数组为 DdbObj[] */
1430
1584
  to_ddbobjs(values) {
1431
- for (let i = 0; i < values.length; i++)
1432
- values[i] = this.to_ddbobj(values[i]);
1433
- return values;
1585
+ return values.map(value => this.to_ddbobj(value));
1434
1586
  }
1435
1587
  }
1436
1588
  exports.DDB = DDB;