node-red-contrib-questdb 0.3.0 → 0.3.2

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.
@@ -755,7 +755,7 @@
755
755
  "type": "function",
756
756
  "z": "questdb-examples-tab",
757
757
  "name": "Generate random metrics",
758
- "func": "msg.payload = {\n symbols: {\n host: \"server-\" + Math.floor(Math.random() * 3 + 1),\n region: [\"us-east\", \"us-west\", \"eu-west\"][Math.floor(Math.random() * 3)]\n },\n columns: {\n cpu: Math.random() * 100,\n memory: Math.random() * 100,\n disk_io: { value: Math.random() * 1000, type: 'double' },\n connections: { value: Math.floor(Math.random() * 1000), type: 'int' },\n // Array of recent latencies\n latency_samples: Array.from({length: 10}, () => Math.random() * 100)\n },\n timestamp: Date.now()\n};\nreturn msg;",
758
+ "func": "msg.payload = {\n symbols: {\n host: \"server-\" + Math.floor(Math.random() * 3 + 1),\n region: [\"us-east\", \"us-west\", \"eu-west\"][Math.floor(Math.random() * 3)]\n },\n columns: {\n cpu: Math.random() * 100,\n memory: Math.random() * 100,\n disk_io: Math.random() * 1000,\n connections: Math.floor(Math.random() * 1000),\n avg_latency: Math.random() * 100\n },\n timestamp: Date.now()\n};\nreturn msg;",
759
759
  "outputs": 1,
760
760
  "x": 410,
761
761
  "y": 1360,
package/nodes/write.js CHANGED
@@ -299,35 +299,60 @@ module.exports = function(RED) {
299
299
  }
300
300
 
301
301
  if (payload.columns && typeof payload.columns === 'object') {
302
+ // Check which methods are available in the sender
303
+ const hasLongColumn = typeof connection.sender.longColumn === 'function';
304
+ const hasDoubleColumn = typeof connection.sender.doubleColumn === 'function';
305
+ const hasArrayColumn = typeof connection.sender.arrayColumn === 'function';
306
+ const hasDecimalColumn = typeof connection.sender.decimalColumn === 'function';
307
+
302
308
  for (const [key, value] of Object.entries(payload.columns)) {
303
309
  if (value === null || value === undefined) continue;
304
310
 
305
311
  // Check for explicit type specification: { value: x, type: 'int'|'long'|'float'|'double'|'decimal'|'array' }
306
- if (typeof value === 'object' && value.type && value.value !== undefined) {
312
+ if (typeof value === 'object' && !Array.isArray(value) && value.type && value.value !== undefined) {
307
313
  const colType = value.type.toLowerCase();
308
314
  const colValue = value.value;
309
315
 
310
316
  if (colType === 'int' || colType === 'integer') {
311
317
  connection.sender.intColumn(key, Math.trunc(colValue));
312
318
  } else if (colType === 'long') {
313
- connection.sender.longColumn(key, BigInt(Math.trunc(colValue)));
319
+ if (hasLongColumn) {
320
+ connection.sender.longColumn(key, BigInt(Math.trunc(colValue)));
321
+ } else {
322
+ // Fallback: use intColumn for smaller values, floatColumn for larger
323
+ const intVal = Math.trunc(colValue);
324
+ if (intVal >= -2147483648 && intVal <= 2147483647) {
325
+ connection.sender.intColumn(key, intVal);
326
+ } else {
327
+ connection.sender.floatColumn(key, colValue);
328
+ }
329
+ }
314
330
  } else if (colType === 'float') {
315
331
  connection.sender.floatColumn(key, colValue);
316
332
  } else if (colType === 'double') {
317
- connection.sender.doubleColumn(key, colValue);
333
+ if (hasDoubleColumn) {
334
+ connection.sender.doubleColumn(key, colValue);
335
+ } else {
336
+ connection.sender.floatColumn(key, colValue);
337
+ }
318
338
  } else if (colType === 'decimal') {
319
- // Decimal: { value: '123.45', type: 'decimal' } or { mantissa: 12345n, scale: 2, type: 'decimal' }
320
- if (value.mantissa !== undefined && value.scale !== undefined) {
321
- connection.sender.decimalColumn(key, BigInt(value.mantissa), value.scale);
339
+ if (hasDecimalColumn) {
340
+ if (value.mantissa !== undefined && value.scale !== undefined) {
341
+ connection.sender.decimalColumn(key, BigInt(value.mantissa), value.scale);
342
+ } else {
343
+ connection.sender.decimalColumnText(key, String(colValue));
344
+ }
322
345
  } else {
323
- // Use text representation
324
- connection.sender.decimalColumnText(key, String(colValue));
346
+ // Fallback: store as string
347
+ connection.sender.stringColumn(key, String(colValue));
325
348
  }
326
349
  } else if (colType === 'array') {
327
- // Array column: { value: [1, 2, 3], type: 'array', elementType: 'double' }
328
- if (Array.isArray(colValue)) {
350
+ if (hasArrayColumn && Array.isArray(colValue)) {
329
351
  const elementType = (value.elementType || 'double').toLowerCase();
330
352
  connection.sender.arrayColumn(key, elementType, colValue);
353
+ } else if (Array.isArray(colValue)) {
354
+ // Fallback: store as JSON string
355
+ connection.sender.stringColumn(key, JSON.stringify(colValue));
331
356
  } else {
332
357
  node.warn(`Array column '${key}' value must be an array`);
333
358
  }
@@ -346,17 +371,22 @@ module.exports = function(RED) {
346
371
 
347
372
  // Array detection (auto)
348
373
  if (Array.isArray(value)) {
349
- // Detect element type from first non-null element
350
- const firstElement = value.find(v => v !== null && v !== undefined);
351
- let elementType = 'double'; // default
352
- if (typeof firstElement === 'string') {
353
- elementType = 'string';
354
- } else if (typeof firstElement === 'boolean') {
355
- elementType = 'boolean';
356
- } else if (typeof firstElement === 'bigint') {
357
- elementType = 'long';
374
+ if (hasArrayColumn) {
375
+ // Detect element type from first non-null element
376
+ const firstElement = value.find(v => v !== null && v !== undefined);
377
+ let elementType = 'double'; // default
378
+ if (typeof firstElement === 'string') {
379
+ elementType = 'string';
380
+ } else if (typeof firstElement === 'boolean') {
381
+ elementType = 'boolean';
382
+ } else if (typeof firstElement === 'bigint') {
383
+ elementType = 'long';
384
+ }
385
+ connection.sender.arrayColumn(key, elementType, value);
386
+ } else {
387
+ // Fallback: store as JSON string
388
+ connection.sender.stringColumn(key, JSON.stringify(value));
358
389
  }
359
- connection.sender.arrayColumn(key, elementType, value);
360
390
  continue;
361
391
  }
362
392
 
@@ -365,10 +395,14 @@ module.exports = function(RED) {
365
395
  node.warn(`Skipping non-finite number for column '${key}'`);
366
396
  continue;
367
397
  }
368
- // Default to double for numbers (most precise)
369
- connection.sender.doubleColumn(key, value);
398
+ // Use floatColumn (available in all versions)
399
+ connection.sender.floatColumn(key, value);
370
400
  } else if (typeof value === 'bigint') {
371
- connection.sender.longColumn(key, value);
401
+ if (hasLongColumn) {
402
+ connection.sender.longColumn(key, value);
403
+ } else {
404
+ connection.sender.floatColumn(key, Number(value));
405
+ }
372
406
  } else if (typeof value === 'boolean') {
373
407
  connection.sender.booleanColumn(key, value);
374
408
  } else if (typeof value === 'string') {
package/nul ADDED
@@ -0,0 +1,46 @@
1
+ [
2
+ "0.0.1",
3
+ "0.0.2",
4
+ "0.0.4",
5
+ "0.0.5",
6
+ "0.0.6",
7
+ "0.0.7",
8
+ "0.0.8",
9
+ "0.0.9",
10
+ "0.0.10",
11
+ "0.0.11",
12
+ "0.0.12",
13
+ "0.0.14",
14
+ "0.0.15",
15
+ "0.0.16",
16
+ "0.0.17",
17
+ "0.0.18",
18
+ "0.0.20",
19
+ "0.0.21",
20
+ "0.0.22",
21
+ "0.0.23",
22
+ "0.0.24",
23
+ "0.0.25",
24
+ "0.0.26",
25
+ "0.0.27",
26
+ "0.0.28",
27
+ "0.0.29",
28
+ "0.0.30",
29
+ "0.0.31",
30
+ "0.0.32",
31
+ "0.0.33",
32
+ "0.0.34",
33
+ "1.0.0",
34
+ "1.0.1",
35
+ "1.0.2",
36
+ "1.0.3",
37
+ "1.0.4",
38
+ "1.0.5",
39
+ "2.0.0",
40
+ "2.1.0",
41
+ "3.0.0",
42
+ "4.0.1",
43
+ "4.0.2",
44
+ "4.1.0",
45
+ "4.2.0"
46
+ ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-questdb",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Node-RED nodes for QuestDB time-series database",
5
5
  "keywords": [
6
6
  "node-red",