@windozer/node-q
v2.6.0
Published
Q interfacing with Node.js
Downloads
153
Readme
node-q
Q interfacing with Node.js. Supports decompression. Can deserialize all q data types (including guid
) to JavaScript. Can serialize all JavaScript data types to q.
Installation
npm install node-q
Usage
Create Connection
var nodeq = require("node-q");
nodeq.connect({host: "localhost", port: 5000}, function(err, con) {
if (err) throw err;
console.log("connected");
// interact with con like demonstrated below
});
Create TLS Connection
var nodeq = require("node-q");
nodeq.connect({host: "localhost", port: 6000, useTLS: true}, function(err, con) {
if (err) throw err;
console.log("connected");
// interact with con like demonstrated below
});
Create Connection with user and password auth
var nodeq = require("node-q");
nodeq.connect({host: "localhost", port: 5000, user: "user", password: "password"}, function(err, con) {
if (err) throw err;
console.log("connected");
// interact with con like demonstrated below
});
Create Connection with Unix Domain Socket (Doesn't support abstract namespace sockets: KDB 3.5+ on Linux)
nodeq.connect({ unixSocket: "/path/to/socket" }, function(err, con) {
if (err) throw err;
console.log("connected");
});
Execute Q code and receive result
con.k("sum 1 2 3", function(err, res) {
if (err) throw err;
console.log("result", res); // 6
});
Execute function with one parameter and receive result
con.k("sum", [1, 2, 3], function(err, res) {
if (err) throw err;
console.log("result", res); // 6
});
Execute function with two parameters and receive result
con.k("cor", [1, 2, 3], [4, 5, 6], function(err, res) {
if (err) throw err;
console.log("result", res); // 1
});
Async execute Q code
con.ks("show 1 2 3", function(err) {
if (err) throw err;
});
Async execute function with parameters
con.ks("show", [1, 2, 3], function(err) {
if (err) throw err;
});
Listen to a handle
con.k(function(err, res) {
if (err) throw err;
console.log("result", res);
});
Subscribe to kdb+tick
con.on("upd", function(table, data) {
console.log(table, data);
});
con.ks(".u.sub[`;`]", function(err) { // subscribe to all tables and all symbols
if (err) throw err;
});
Close connection
con.close(function() {
console.log("con closed");
});
Types
q has more data types than JavaScript. Therefore you need to know how types are converted.
From q to JavaScript (deserialization)
| q type | JavaScript type | Null | +Infinity | -Infinity | | ------ | --------------- | ---- | --------- | --------- | | boolean | Boolean | | | | | guid | String | Null | | | | byte | Number | | | | | short | Number | Null | Infinity | -Infinity | | int | Number | Null | Infinity | -Infinity | | long | Number 5 | Null | Infinity | -Infinity | | real | Number | Null | Infinity | -Infinity | | float | Number | Null | Infinity | -Infinity | | char | String | Null 4 | | | | symbol | String | Null | | | | timestamp | Date 1, 2 | Null | | | | month | Date 2 | Null | | | | date | Date 2 | Null | | | | datetime | Date 2 | Null | | | | timespan | Date 1, 2, 3 | Null | | | | minute | Date 2, 3 | Null | | | | second | Date 2, 3 | Null | | | | time | Date 2, 3 | Null | | |
- 1: q comes with nanoseconds precision. JavaScript only with milliseconds. You can disable
nanos2date
deserialization duringconnect(params, cb)
to get the nanoseconds timestamp as a plain Number. - 2: think about running your Node.js process with
TZ=UTC node ...
to run in UTC timezone. q doesn't know timezones. - 3: date is set to
2000-01-01
in the Date object. Only evaluate the time part. - 4: You can disable
emptyChar2null
deserialization duringconnect(params, cb)
to keep the empty char. - 5: You can disable
long2number
deserialization duringconnect(params, cb)
to represent longs as long.js.
dict
q) (`a`b`c)!(1 2 3i)
becomes Object
{
a: 1,
b: 2,
c: 3
}
list
q) 1 2 3i
becomes Array
[1, 2, 3]
table
q) ([] sym:`a`b`c; size:(1 2 3i))
becomes Array of Object per row.
[
{sym: "a", size: 1},
{sym: "b", size: 2},
{sym: "c", size: 3}
]
You can disable flipTables
during connect(params, cb)
to get a table as an Object with an Array per column.
{
sym: ["a", "b", "c"],
size: [1, 2, 3]
}
From JavaScript to q (serialization)
Simple (infer type)
| JavaScript type | q type | | --------------- | ------ | | Boolean | boolean | | String starting with ` | symbol | | String | list[char] | | Number | float | | Date | datetime | | Object | dict | | Array[] | list[] | | Null | unary primitive | | Infinity | float | | -Infinity | float |
Advanced (explicit types)
If you want to explicitly serialize a JavaScript type as a q type you need to use the typed API.
Let's start with two examples:
con.k("type", nodeq.short(1), function(err, res) {
if (err) throw err;
console.log("result", res); // -5
});
con.k("type", nodeq.shorts([1, 2, 3]), function(err, res) {
if (err) throw err;
console.log("result", res); // 5
});
For every primitive type in q, this module exports a method to wrap the JavaScript value. You can also wrap a JavaScript array into a q type by appending an s to the primitive wrapper's name.
| q type | primitive wrapper | array wrapper |
| ------ | ----------------- | ------------- |
| boolean | boolean(Boolean)
| booleans(Array[Boolean])
|
| guid | guid(String)
| guids(Array[String])
|
| byte | byte(Number)
| bytes(Array[Number])
|
| short | short(Number)
| shorts(Array[Number])
|
| int | int(Number)
| ints(Array[Number])
|
| long | long(long)
1 | longs(Array[long])
1 |
| real | real(Number)
| reals(Array[Number])
|
| float | float(Number)
| floats(Array[Number])
|
| char | char(String)
| chars(Array[String])
|
| symbol | symbol(String)
| symbols(Array[String])
|
| timestamp | timestamp(Date)
| timestamps(Array[Date])
|
| month | month(Date)
| months(Array[Date])
|
| date | date(Date)
| dates(Array[Date])
|
| datetime | datetime(Date)
| datetimes(Array[Date])
|
| timespan | timespan(Date)
| timespans(Array[Date])
|
| minute | minute(Date)
| minutes(Array[Date])
|
| second | second(Date)
| seconds(Array[Date])
|
| time | time(Date)
| times(Array[Date])
|
- 1: JavaScript can not represent 64bit longs. Therefore this module uses the long.js module to represent longs.
API
connect(params, cb)
params
: Objecthost
: String (e. g. "localhost") (optional)port
: Number (e. g. 5000) (optional)unixSocket
: String (e. g. "/path/to/socket") (optional)user
: String (optional)password
: String (optional)useTLS
: Boolean (optional)socketNoDelay
: Boolean (optional, see http://nodejs.org/api/net.html#net_socket_setnodelay_nodelay)socketTimeout
: Number (optional, see http://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback)nanos2date
: Boolean (optional, default: true)flipTables
: Boolean (optional, default: true)emptyChar2null
: Boolean (optional, default: true)long2number
: Boolean (optional, default: true)
cb
: Function(err
,con
)err
:Error
orundefined
conn
:Connection
orundefined
@deprecated connect(host, port, [user, password,] cb)
This is deprecated. Please use the new, mor flexible API above!
host
: String (e. g. "localhost")port
: Number (e. g. 5000)user
: String (optional)password
: String (optional)
Connection
Is an EventEmitter.
k(s, [x, [y, [z, [...,] ] ] ] cb)
Sync request/response.
s
: Stringx
: Object (optional)y
: Object (optional)z
: Object (optional)...
: Object (optional)cb
: Function(err
,res
)err
:Error
orundefined
res
:Object
orundefined
ks(s, [x, [y, [z, [...,] ] ] ] cb)
Async request.
s
: Stringx
: Object (optional)y
: Object (optional)z
: Object (optional)...
: Object (optional)cb
: Function(err
)err
:Error
orundefined
close(cb)
cb
: Function(err
) (optional)err
:Error
orundefined
Events
upd(table, data)
If you use kdb+tick and subscribe like con.ks(".u.sub[
;]", function(err) { throw err; })
you will receive all Updates via upd
Event.
error(err)
If the socket emit an error
event.
err
:Error
end()
If the socket emit an end
event.
timeout()
If the socket emit a timeout
event.
close(had_error)
If the socket emit a close
event.
had_error
: Boolean (true if the socket had a transmission error)
Contribution
If you want to create a Pull-Request please make sure that make test
runs without failures.
If you have a kdb+tick setup please also run make mochait
.
Code Style
make jshint
Unit Tests
make mocha
Integration Test
Assumes a running q process on port 5000 with kdb+tick available in QHOME (QHOME=~/q ~/q/m32/q -p 5000
). For the tls tests you will also need a running q process on port 6000 set up to require tls. Instructions for this can be found here. If you are using a self signed certificate you will also need to set the NODE_TLS_REJECT_UNAUTHORIZED
environment variable to 0
.
make mochait
Circular depdendencies
make circular