@@ -246,6 +246,217 @@ describe("Sender tests with containerized QuestDB instance", () => {
246
246
await sender . close ( ) ;
247
247
} ) ;
248
248
249
+ it ( "can ingest data via HTTP with protocol v2" , async ( ) => {
250
+ const tableName = "test_http_v2" ;
251
+ const schema = [
252
+ { name : "location" , type : "SYMBOL" } ,
253
+ { name : "temperatures" , type : "ARRAY" , elemType : "DOUBLE" , dim : 1 } ,
254
+ { name : "timestamp" , type : "TIMESTAMP" } ,
255
+ ] ;
256
+
257
+ const sender = await Sender . fromConfig (
258
+ `http::addr=${ container . getHost ( ) } :${ container . getMappedPort ( QUESTDB_HTTP_PORT ) } ;auto_flush_rows=1` ,
259
+ ) ;
260
+
261
+ // ingest via client
262
+ await sender
263
+ . table ( tableName )
264
+ . symbol ( "location" , "us" )
265
+ . arrayColumn ( "temperatures" , [ 17.1 , 17.7 , 18.4 ] )
266
+ . at ( 1658484765000000000n , "ns" ) ;
267
+
268
+ // wait for the table
269
+ await waitForTable ( container , tableName ) ;
270
+
271
+ // query table
272
+ const select1Result = await runSelect ( container , tableName , 1 ) ;
273
+ expect ( select1Result . query ) . toBe ( tableName ) ;
274
+ expect ( select1Result . count ) . toBe ( 1 ) ;
275
+ expect ( select1Result . columns ) . toStrictEqual ( schema ) ;
276
+ expect ( select1Result . dataset ) . toStrictEqual ( [
277
+ [ "us" , [ 17.1 , 17.7 , 18.4 ] , "2022-07-22T10:12:45.000000Z" ] ,
278
+ ] ) ;
279
+
280
+ // ingest via client, add new columns
281
+ await sender
282
+ . table ( tableName )
283
+ . symbol ( "location" , "us" )
284
+ . arrayColumn ( "temperatures" , [ 17.36 , 18.4 , 19.6 , 18.7 ] )
285
+ . at ( 1658484765000666000n , "ns" ) ;
286
+ await sender
287
+ . table ( tableName )
288
+ . symbol ( "location" , "emea" )
289
+ . symbol ( "city" , "london" )
290
+ . arrayColumn ( "temperatures" , [ 18.5 , 18.4 , 19.2 ] )
291
+ . floatColumn ( "daily_avg_temp" , 18.7 )
292
+ . at ( 1658484765001234000n , "ns" ) ;
293
+
294
+ // query table
295
+ const select2Result = await runSelect ( container , tableName , 3 ) ;
296
+ expect ( select2Result . query ) . toBe ( tableName ) ;
297
+ expect ( select2Result . count ) . toBe ( 3 ) ;
298
+ expect ( select2Result . columns ) . toStrictEqual ( [
299
+ { name : "location" , type : "SYMBOL" } ,
300
+ { name : "temperatures" , type : "ARRAY" , elemType : "DOUBLE" , dim : 1 } ,
301
+ { name : "timestamp" , type : "TIMESTAMP" } ,
302
+ { name : "city" , type : "SYMBOL" } ,
303
+ { name : "daily_avg_temp" , type : "DOUBLE" } ,
304
+ ] ) ;
305
+ expect ( select2Result . dataset ) . toStrictEqual ( [
306
+ [ "us" , [ 17.1 , 17.7 , 18.4 ] , "2022-07-22T10:12:45.000000Z" , null , null ] ,
307
+ [
308
+ "us" ,
309
+ [ 17.36 , 18.4 , 19.6 , 18.7 ] ,
310
+ "2022-07-22T10:12:45.000666Z" ,
311
+ null ,
312
+ null ,
313
+ ] ,
314
+ [
315
+ "emea" ,
316
+ [ 18.5 , 18.4 , 19.2 ] ,
317
+ "2022-07-22T10:12:45.001234Z" ,
318
+ "london" ,
319
+ 18.7 ,
320
+ ] ,
321
+ ] ) ;
322
+
323
+ await sender . close ( ) ;
324
+ } ) ;
325
+
326
+ it ( "can ingest NULL array via HTTP with protocol v2" , async ( ) => {
327
+ const tableName = "test_http_v2_null" ;
328
+ const schema = [
329
+ { name : "location" , type : "SYMBOL" } ,
330
+ { name : "temperatures" , type : "ARRAY" , elemType : "DOUBLE" , dim : 1 } ,
331
+ { name : "timestamp" , type : "TIMESTAMP" } ,
332
+ ] ;
333
+
334
+ const sender = await Sender . fromConfig (
335
+ `http::addr=${ container . getHost ( ) } :${ container . getMappedPort ( QUESTDB_HTTP_PORT ) } ` ,
336
+ ) ;
337
+
338
+ // ingest via client
339
+ await sender
340
+ . table ( tableName )
341
+ . symbol ( "location" , "us" )
342
+ . arrayColumn ( "temperatures" , [ 17.1 , 17.7 , 18.4 ] )
343
+ . at ( 1658484765000000000n , "ns" ) ;
344
+ await sender
345
+ . table ( tableName )
346
+ . symbol ( "location" , "gb" )
347
+ . at ( 1658484765000666000n , "ns" ) ;
348
+ await sender . flush ( ) ;
349
+
350
+ // wait for the table
351
+ await waitForTable ( container , tableName ) ;
352
+
353
+ // query table
354
+ const select1Result = await runSelect ( container , tableName , 2 ) ;
355
+ expect ( select1Result . query ) . toBe ( tableName ) ;
356
+ expect ( select1Result . count ) . toBe ( 2 ) ;
357
+ expect ( select1Result . columns ) . toStrictEqual ( schema ) ;
358
+ expect ( select1Result . dataset ) . toStrictEqual ( [
359
+ [ "us" , [ 17.1 , 17.7 , 18.4 ] , "2022-07-22T10:12:45.000000Z" ] ,
360
+ [ "gb" , null , "2022-07-22T10:12:45.000666Z" ] ,
361
+ ] ) ;
362
+
363
+ await sender . close ( ) ;
364
+ } ) ;
365
+
366
+ it ( "can ingest empty array via HTTP with protocol v2" , async ( ) => {
367
+ const tableName = "test_http_v2_empty" ;
368
+ const schema = [
369
+ { name : "location" , type : "SYMBOL" } ,
370
+ { name : "temperatures" , type : "ARRAY" , elemType : "DOUBLE" , dim : 1 } ,
371
+ { name : "timestamp" , type : "TIMESTAMP" } ,
372
+ ] ;
373
+
374
+ const sender = await Sender . fromConfig (
375
+ `http::addr=${ container . getHost ( ) } :${ container . getMappedPort ( QUESTDB_HTTP_PORT ) } ` ,
376
+ ) ;
377
+
378
+ // ingest via client
379
+ await sender
380
+ . table ( tableName )
381
+ . symbol ( "location" , "us" )
382
+ . arrayColumn ( "temperatures" , [ 17.1 , 17.7 , 18.4 ] )
383
+ . at ( 1658484765000000000n , "ns" ) ;
384
+ await sender
385
+ . table ( tableName )
386
+ . symbol ( "location" , "gb" )
387
+ . arrayColumn ( "temperatures" , [ ] )
388
+ . at ( 1658484765000666000n , "ns" ) ;
389
+ await sender . flush ( ) ;
390
+
391
+ // wait for the table
392
+ await waitForTable ( container , tableName ) ;
393
+
394
+ // query table
395
+ const select1Result = await runSelect ( container , tableName , 2 ) ;
396
+ expect ( select1Result . query ) . toBe ( tableName ) ;
397
+ expect ( select1Result . count ) . toBe ( 2 ) ;
398
+ expect ( select1Result . columns ) . toStrictEqual ( schema ) ;
399
+ expect ( select1Result . dataset ) . toStrictEqual ( [
400
+ [ "us" , [ 17.1 , 17.7 , 18.4 ] , "2022-07-22T10:12:45.000000Z" ] ,
401
+ [ "gb" , [ ] , "2022-07-22T10:12:45.000666Z" ] ,
402
+ ] ) ;
403
+
404
+ await sender . close ( ) ;
405
+ } ) ;
406
+
407
+ it ( "can ingest multi dimensional empty array via HTTP with protocol v2" , async ( ) => {
408
+ const tableName = "test_http_v2_multi_empty" ;
409
+ const schema = [
410
+ { name : "location" , type : "SYMBOL" } ,
411
+ { name : "temperatures" , type : "ARRAY" , elemType : "DOUBLE" , dim : 2 } ,
412
+ { name : "timestamp" , type : "TIMESTAMP" } ,
413
+ ] ;
414
+
415
+ const sender = await Sender . fromConfig (
416
+ `http::addr=${ container . getHost ( ) } :${ container . getMappedPort ( QUESTDB_HTTP_PORT ) } ` ,
417
+ ) ;
418
+
419
+ // ingest via client
420
+ await sender
421
+ . table ( tableName )
422
+ . symbol ( "location" , "us" )
423
+ . arrayColumn ( "temperatures" , [
424
+ [ 17.1 , 17.7 ] ,
425
+ [ 18.4 , 18.7 ] ,
426
+ ] )
427
+ . at ( 1658484765000000000n , "ns" ) ;
428
+ await sender
429
+ . table ( tableName )
430
+ . symbol ( "location" , "gb" )
431
+ . arrayColumn ( "temperatures" , [ [ ] , [ ] ] )
432
+ . at ( 1658484765000666000n , "ns" ) ;
433
+ await sender . flush ( ) ;
434
+
435
+ // wait for the table
436
+ await waitForTable ( container , tableName ) ;
437
+
438
+ // query table
439
+ const select1Result = await runSelect ( container , tableName , 2 ) ;
440
+ expect ( select1Result . query ) . toBe ( tableName ) ;
441
+ expect ( select1Result . count ) . toBe ( 2 ) ;
442
+ expect ( select1Result . columns ) . toStrictEqual ( schema ) ;
443
+ expect ( select1Result . dataset ) . toStrictEqual ( [
444
+ [
445
+ "us" ,
446
+ [
447
+ [ 17.1 , 17.7 ] ,
448
+ [ 18.4 , 18.7 ] ,
449
+ ] ,
450
+ "2022-07-22T10:12:45.000000Z" ,
451
+ ] ,
452
+ // todo: this should be [[], []]
453
+ // probably a server bug
454
+ [ "gb" , [ ] , "2022-07-22T10:12:45.000666Z" ] ,
455
+ ] ) ;
456
+
457
+ await sender . close ( ) ;
458
+ } , 60000000 ) ;
459
+
249
460
it ( "can ingest data via HTTP with auto flush interval" , async ( ) => {
250
461
const tableName = "test_http_interval" ;
251
462
const schema = [
0 commit comments