Skip to content

kdb+ 4.0 Release Notes

This page details the latest features and improvements released to kdb+ 4.0.

2026.07.06

Fixes and improvements

  • computing average of more than 2147483647 rows from a partitioned table returned wrong result due to overflow since 3.3

    q)(`:T/2000.01.01/t/;`:T/2000.01.02/t/) set\: ([]1073741824#1b)
    q)\l T/
    q)select avg x from t
    raze now elides copy from both leading and trailing empty lists
  • anymap like enlist"*" threw 'type even if all elements were strings, e.g.

    q)get[`:v set ("abc";"def")]like enlist"*"
    11b
  • "\n"$ was segfaulting, e.g.

    q)"\n"$("123";"456")
    'type
  • partitioned functional select was stripping the sorted attribute from step dictionaries, e.g.

    q)`:HDB/2026.02.10/test/ set([]time:0 2 4);system"l HDB";?[test;();0b;`time`bucket!(`time;(`s#1 3!`closed`open;`time))]
    time bucket
    -----------
    0
    2    closed
    4    open
    the profiler could leave the target in a stopped state when the latter read compressed data
  • x*/y with byte or short x returned wrong result since kdb+3.3, e.g.

    q)0x01*/0x01020304
    q)1h*/1 2 3 4h
    consistently handle a&/`s#b and a|/`s#b which has been igoring seed for a nonempty array since 3.1
    q)0&/`s#1 2 3

2026.01.23

New

  • windows license check includes an additional check of comparing with hostname.domainname where domainname is retrieved from the DNS associated with the local computer. linux/mac already perform this check.

  • this is in addition to the windows lookup of the host/domain via IP. Ref: https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getcomputernameexa (ComputerNameDnsDomain)

  • license error due to host mismatch now contains extra information (domain and dns) e.g. "'license error: host testbox" can now be presented in the style "'license error: host testbox.domain host.docker.internal)"

Fixes and improvements

  • pressing Ctrl+C on Windows stopped the console from responding, since Windows 8

2025.12.18

Fixes and improvements

  • in very rare cases, sorting could hang, since 3.5

  • .q_ and .k_ files are now also loaded from db root when loading a database

  • upserting a sorted column without `s# attribute to a sorted splayed column is now append when applicable

  • profile could sometimes seg-fault

2025.02.18

Fixes and improvements

  • since 2.7 2011.11.18, drop (_) on a partitioned or non existent splayed table could crash e.g.

    q)@[flip[`a`b!`:foobar]_;0;::]
  • since 4.0 2023.01.20, .Q.ld could erroneously modify it's input, e.g.

    q)lines:("aaa ";"bbb");.Q.ld lines;lines
    "aaa"
    "bbb"

2025.01.31

Fixes and improvements

  • since 4.1 2025.01.17, after running .Q.MAP, certain queries on partitioned tables could error with length e.g.

    q)select i from t where i=0,{x=0}[i]

2025.01.17

New

  • for queries on partitioned tables in segmented databases, delay materializing results when results exist only in one segment for a table.

Fixes and improvements

  • .Q.res now includes fromby

  • using hclose on recieving socket within .z.ac (http auth) could send unsent response

  • to subsequent connection, resulting in badmsg error.

    q)\p 5000
    q).z.ac:{[x]hclose .z.w;(2;"HTTP/1.1 401 Unauthorized\r\nConnection: close\r\n\r\n")}
    client:
    q)`:http://localhost:5000 "GET / HTTP/1.1\r\n\r\n"
    q)h:hopen 5000
    'badmsg
    see documentation for .z.ac, returning appropriate response will close the socket automatically
    after calling .Q.MAP[], certain queries involving the partition field could result in a 'length error
    q)select date,sym from trade
    'length
    q)select by sym,date from trade
    'length
    q)select from trade where sym=`AAA,date=.z.D
    'length
  • appending vectors or tables to type 0 lists with `g# attribute could seg-fault, e.g.

    q)a:`g#1#(::);a,:100#`s
    q)a:`g#1 1#(::);a,:100#([]`a`b`c)

2024.07.08

Fixes and improvements

  • abnormal exits, e.g. -w abort, would be attempted from several threads at once, causing repeated output and potential crashes

  • for anymap objects written with 1:, prototype was erroneously computed to be (), leading to 'length error on update for tables with leading anymap columns, e.g.

    q)a:get`:a 1:((1 2;3 4);(5 6;7 8));  (0#0;0#0)~a 0N / was: ()~a 0N
    q)update c:8,d:9 from ([]a) where i=1               / was 'length
    0 wavg (1 2;3 4) would return scalar 0n, since 2021.09.03

2024.03.04

Fixes and improvements

  • Websocket subprotocol kxnodeflate was failing if the client did not request permessage-deflate or the server did not have zlib loaded, since v4.0 2024.02.22.

2024.03.02

New

  • extended -36! (load Data-At-Rest-Encryption key) to:

    1)Expose whether a key has already been loaded, via -36!(::), returning 0b or 1b accordingly.
    2)Lock -36! to avoid loading of another key, via -36!(`:keyfile;"password";bool), where bool indicates unlock/lock. To reload using a new key, unlock using current key and then proceed with the new key
    If load is attempted whilst locked, it throws 'DARE key locked.

Fixes and improvements

  • Using websocket subprotocol kxnodeflate was failing to disable compression since v4.0 2024.02.22.

2024.02.22

New

  • Now recognizes sec-websocket-protocol http header with value kxnodeflate to disable websocket compression. e.g.

    javascript in browser:h=WebSocket("ws://host:port","kxnodeflate")

2024.02.09

Fixes and improvements

  • in a partitioned select, projections used with aggregates could signal 'type, e.g.

    q)select %[;2]sum a from t
  • csv export of symbol or character vector values containing newlines "\n" are now enclosed in double quotes e.g.

    q)csv 0:([]("foo\nbar";"baz"))
    ,"x"
    "\"foo\nbar\""
    "baz"
    file read of sym, where sym has length greater than 2097151, no longer result in parse error
    q)get `:lsym set a:`$2097153#"a"
  • fill (^) with keyed tables could give inconsistent results depending on the key order, since v 3.2, e.g.

    q)([k:1 2 3]s:110b;t:1 2 3)^([k:1 2 3]t:3 4 5)
    k| s t
    -| ---
    1| 1 3
    2| 1 4
    3| 0 5
    q)([k:1 2 3]s:110b;t:1 2 3)^reverse ([k:1 2 3]t:3 4 5)
    k| s t
    -| ---
    1| 0 3
    2| 0 4
    3| 0 5
  • in a compressed hdb after .Q.MAP[], internal file descriptors were leaked to children, visible with e.g. system"ls -l /proc/self/fd"

2024.02.06

NUC (Not Upwardly Compatible)

Not backward compatible. Changes existing behavior.

  • Loading shared libraries via 2: was resolving to a canonical path prior to load via the OS, since v3.6 2018.08.24; this caused issues for libs whose run-time path was relative to a sym-link. Now it resolves to an absolute path only, without resolving sym-links.

2023.11.03

New

  • during process init, getpwuid can fall back on envvars HOME and USER

Fixes and improvements

  • when writing anymap, empty vectors w/o attributes get deduplicated automatically (including enum vectors when enum name is 'sym')

2023.08.11

NUC (Not Upwardly Compatible)

Not backward compatible. Changes existing behavior.

  • hdel now signals 'access when used in reval or -b (blocked) mode, e.g.

    q)hopen[4000]"reval(hdel;enlist`:somefile)"
    'access: somefile
  • hopen on a file now applies access rules when used in reval, -b (blocked) mode, or with -u 1/file, e.g.

    q)h:hopen 4000 / to a server started with -u 1 -p 4000
    q)h"reval(hopen;enlist`:somefile)"
    'access: somefile
    q)h"hopen`:../somefile"
    'access: ../somefile
  • hopen on a fifo now applies access rules when used with -u 1/file, e.g.

    q)hopen[4000]"hopen`:fifo://../somefifo" / to a server started with -u 1 -p 4000
    'access: ../somefifo

Fixes and improvements

  • in partitioned table queries, references to linked columns under group by no longer require remapping the foreign column for every group

    q)select link.x by sym from trade

2023.05.26

Fixes and improvements

  • using mtim (multithreaded input mode) with socket sharding could cause an instance to hang

  • Calling parse or -4! with input over 2gb (0Wi) could cause crash. now returns domain error. e.g.

    q)parse "a:3",0wi#"0"
  • JSON serialization of negative minute/second/time/timespan types incorrect since 3.6 (2017.10.13) e.g.

    q).j.j([]startTime:-08:00 -06:30;endTime:16:00 -04:00)
  • "x"$ on longs over 0Wi is now consistent with lower values, e.g.

    q)0xfeff00~"x"$-1 0 1+0Wi
    Corruption of .Q.pt could occur when providing .Q.view with a value that resulted
  • in no matches with .Q.PV (partition values). Now returns error "invalid partition filter".

  • key`:nfsmnt/ could signal ENOENT error, rather than ()

  • key`:filesymlink on windows now signals error when no access permissions to reach target file

  • key`:path/file on linux/mac now returns () when path contains a regular (non-dir) file

2023.04.17

Fixes and improvements

  • on linux/mac, kdb+ could seg-fault if at least one TLS connection was present, and a new connection was assigned a socket descriptor above 1010.

2023.03.28

New

  • function .Q.ld exposes logic used by \l to group script lines for evaluation

    q).Q.ld read0`:funcs.q
    1                   2                5                    6
    "/ multi line func" "f:{\n  x+y\n }" "/ single line func" "g:{x*y}"

Fixes and improvements

  • cmd line option -s now works with kx.lic

  • debugger could return incorrect line numbers for multi-line functions containing multi-line comments

  • a link column with domain of a partitioned table requires the encompassing table to be partitioned too. could crash

  • when given a keyed table, now returns par error e.g.

    q).Q.dd[`:/tmp/db1;`2022.01.01`ecfmapping`] set .Q.en[`:/tmp/db1] ([]firmName:enlist "DUMMY")
    q)\l /tmp/db1
    q)select ecfmap.firmName from ([id:1 2];ecfmap:`ecfmapping!1 1)

2023.03.17

Fixes and improvements

  • reading scalar projections or compositions threw 'parse since initial release of v4.0. e.g

    q)all{x~get`:parse.bin set x}each(1+;'[sum;avg])

2023.03.01

Fixes and improvements

  • concurrent anymap writes could result in broken files since kdb+4.0 2023.01.20, e.g.

    q)v:(3?4000)#'"a";n:`$":a",/:string til system"s";{x set 100000?v}peach n;all{all (distinct get x)in v} peach n

2023.01.20

New

  • anymap write now detects consecutive deduplicated (address matching) toplevel objects, skipping them to save space

    q)a:("hi";"there";"world");`:a0 set a;`:a1 set a@where 1000 2000 3000;(hcount`$":a0#")=hcount`$":a1#"
  • improved memory efficiency of writing nested data sourced from a type 77 file, commonly encountered during compression of files. e.g.

    q)`:a set 500000 100#"abc";system"ts `:b set get`:a" / was 76584400 bytes, now 8390208.

Fixes and improvements

  • windows will now pick up versions of openssl prior to v3

  • aggregation of non-vector types by type short with negative values failed with 'length

    q)select sum x by y from ([](1 2;3 4);y:-1 1h)

2022.12.02

NUC (Not Upwardly Compatible)

Not backward compatible. Changes existing behavior.

  • .z.o for mac universal binary on arm returns m64, previouslym64arm

New

  • x) will try to load x.k_ if loading x.k fails

  • new licensing option: kx.lic

Fixes and improvements

  • reading with 1: no longer strips quotes, e.g. ("abcd";"\"ef\"")~first each("**";4 4)1:"abcd\"ef\""

2022.10.26

NUC (Not Upwardly Compatible)

Not backward compatible. Changes existing behavior.

  • .Q.id for atom now produces `a when contains single character that is not in .Q.an (instead of empty sym) e.g

    q).Q.id`$"+"
    `a  (previous version returned `)
  • .Q.id for atom changes are reflected in .Q.id for tables (as before, it was applied to each column name).

  • .Q.id for tables also has additional logic to cater for duplicate col names (names now appended with 1,2,etc when matched against

  • previous cols) after applying previously defined rules e.g.

    q)cols .Q.id(`$("count+";"count*";"count1"))xcol([]1 2;3 4;5 6)
    `count1`count11`count12  (previous version returned `count1`count1`count1)
    q)cols .Q.id(`$("aa";"=";"+"))xcol([]1 2;3 4;5 6)
    `aa`a`a1  (previous version returned `aa`1`1)
    .Q.id now follows the same rule when provided name begins with an underscore as it does when it begins
  • with a numerical character. Previously could produce an invalid column name.

    q).Q.id`$"_"
    `a_
    q)cols .Q.id(`$("3aa";"_aa";"_aa"))xcol([]1 2;3 4;5 6)
    `a3aa`a_aa`a_aa1

New

  • l64arm build available

  • m64 is now a universal binary, containing both intel and arm builds for macos.

  • use lipo to extract the individual architecture binaries. e.g.

    lipo -thin x86_64 -output q/m64/q.x64 q/m64/q
    lipo -thin arm64  -output q/m64/q.arm q/m64/q
    support for openssl v3
  • on linux, q will now try to load versioned shared libraries for openssl if libssl-dev[el] is not installed.

  • -p cmd line option (or \p system command) can now listen on a port within a specified range e.g.

    q)\p 80/85
    q)\p
    81
  • range of ports is inclusive & tried in a random order. A service name can be used instead of a port number. The existing

  • option of using 0W to choose a free ephemeral port can be more efficient (where suitable).

  • range can be used in place of port number, when setting using existing rules e.g. for hostname

    q)\p myhost:2000/2010
    or for multithreaded port
    q)\p -2000/2010

Fixes and improvements

  • q could fail to connect to licensing servers on startup intermittently whilst running under an on-demand licence.

  • the on-demand system now honours the NO_PROXY/no_proxy environment variables, with the lowercase version taking precedence.

2022.08.19

Fixes and improvements

  • removed redundant system call to unlink() file## when appending to nested/anymap file

2022.07.01

New

  • clock source for walltime (used by .z.p,.z.n) on linux now returns nanosecond precision

  • append detected hostname onto license "host" error message, e.g.

    'license error: host my-machine-hostname

2022.05.11

Fixes and improvements

  • multicolumn search could return wrong results for v3.5 enums and small rhs, since kdb+4.0 2020.07.15

    q)`:oldenum set `:sym?`a`b`c / in v3.5 or earlier
    q)1 0 3 1~([]1 2 3;get`:oldenum)?([]2 1 0 2;`:sym?`b`a`c`b)

2022.04.15

New

  • d9 no longer modifies the reference count of its argument

2022.01.14

Fixes and improvements

  • retain compression settings when appending to a compressed file and the file was recreated. e.g.

    q).z.zd:17 2 6;`:file set();system"x .z.zd";`:file upsert 1000#0;-21!`:file
  • appending a vector to an empty file was leaking file descriptors. e.g.

    q)(`:empty set())upsert 0 1

2021.12.07

Fixes and improvements

  • select with a symbol literal under simple aggregate could seg-fault, e.g.

    q)select sum a*(`aaf=`aaf)|(`aaf=`aaf)|(`aaf=`aaf) by b from ([]a:1 2;b:3 4)
  • with threads enabled, race condition on generating system error messages on non-windows platforms.

2021.11.04

New

  • using -25! with a null handle will print '0N' as the handle in the error message, previously would print '-9223372036854775808'

Fixes and improvements

  • q could crash on startup whilst reading a malformed k4.lic (e.g. kc.lic renamed to k4.lic)

  • all peach and mtim threads are now properly interrupted by ^C/SIGINT/timer.

  • on linux, processes started by \q would not be cleaned up on exit, shown as state Z or in ps output, again since 4.1t 2021.03.30 / 4.0 2021.04.06

  • .Q.gz was not processing compressed data larger than 4GB. e.g.

    q)r~.Q.gz .Q.gz(6;r:4294967295?0x00)
  • misleading 'OS reports: File exists' when malformed .z.zd is used to write compressed files, now reports 'file compression..., e.g.

    q).z.zd:();`:/tmp/aaa set til 10
    'file compression - expecting (blockSize;algo;zipLevel) or filenames!((blockSize;algo;zipLevel);...)

2021.10.15

Fixes and improvements

  • improved limit check for where long vector, was seg-faulting when input overflowed, e.g.

    q)where 0W 0W 1 1
  • "H"$" " was parsing as 0h rather than 0Nh, since 4.0 2021.10.01, e.g.

    q)0Nh~"H"$" "

2021.10.01

New

  • parsing values outside of the short domain was clamping them to ±0Wh instead of to 0Nh. e.g.

    q)0Nh~"H"$"32768"

Fixes and improvements

  • .Q.gz was throwing type when compressing byte vectors. e.g.

    q){x~"c"$.Q.gz .Q.gz(6;"x"$x)}10000#"helloworld"
  • select with a simple aggregate on table-valued column and where clause was throwing 'type, e.g.

    q)select last x by n:i from ([]([]a:enlist"AB")) where i=0
  • loading a splayed table with a column named ` could seg-fault, now loading and saving is blocked signalling 'domain.

  • .Q.dpft .Q.dpfts now require the `p# column (f argument) to be present in the table.

    0 wavg x is now 0n, consistent with other cases, e.g.
    q)0 wavg 0 1
    0n / previously 0.5
  • display for 0Wh was not consistent with 0Wi, as it printed the underlying value 32767h. e.g.

    q)"0Wh"~-3!0Wh
  • http server 'authorization' header had garbled credentials for non-basic auth.

  • creating loadable functions via 2: or dl in the c-api would leak memory since 4.0 2020.03.09

  • partitions ending in $ were not ignored when using segments(par.txt).

2021.07.12

New

  • extended the range of .z.ac to (4;"") to indicate fallback to try authentication via .z.pw.

Fixes and improvements

  • variables in namespaces ".m*" could be incorrectly assigned to memory domain 1, e.g.

    q)-120!'.mm.a:1
    1

2021.06.11

Fixes and improvements

  • select from([]1 2)where i=0i would signal 'type.

  • select from([]1 2)where i in 0 would signal 'type.

  • writing anymap-backed lambdas or symbol vectors w/attributes to anymap could seg-fault:

    q)`:x set get `:x set (`s;{([]s:1)};`a`b;`g#`c`a`b;`a`b)

2021.04.26

Fixes and improvements

  • writes to compressed files did not retry when data was only partially written by the OS, leaving the file unreadable, present since v2.8

2021.04.06

Fixes and improvements

  • "system" could fail on unix since 2021.03.25

2021.03.25

New

  • on windows builds, tcp send and receive buffers are no longer set to fixed sizes allowing autotuning by the OS.

Fixes and improvements

  • an error response to a sync ipc request would leave the handle in a blocking mode, potentially stalling kdb+ until another message was received on that same handle.

  • added additional check to file decompression using ipc algo; was segfaulting. e.g.

    q).z.zd:17 1 0;`:zfile set 100000?100;system"printf '\x31\xc0\xc3' | dd of=zfile bs=1 seek=20 count=3 conv=notrunc";get`:zfile
    on linux, processes started by \q would not be cleaned up on exit, shown as state Z or <defunct> in ps output, since 4.0

2021.02.02

Fixes and improvements

  • in rare circumstances (e.g. when internal functions are overwritten), debugger started from a non-lambda frame could seg-fault.

  • on-disk vectors with no or sorted attribute are now bitwise consistent under append (with unused data zeroed on write), e.g.

    read1[`:x set 1 2 3 4]~read1(`:x set 1 2)upsert 3 4
  • running kdb+ under on demand licensing could cause memory corruption with an infrequent hang or seg-fault, most likely at startup.

2021.01.20

New

  • the result of dlerror is appended to the error message if there is an error loading compression or encryption libraries e.g. (without snappy installed)

    .z.zd:17 3 6
    `:a set til 1000000
    'a. snappy libs required to compress a$. libsnappy.so.1: cannot open shared object file: No such file or directory
    [0]  `:a set til 1000000

Fixes and improvements

  • `#x did not remove the s attr when x was an anymap. e.g.

    q)`~attr`#get`:anymap set`s#("abc";"def")
    'select .. where `p#x in y' could seg-fault for mixed list y, since 2020.09.22. e.g.
    q)select i from ([]`p#1 2 3) where x in (1 2 3;4 5 6)
  • parts-of-time cast of timespan type would overflow to 0Wi for values outside time type range [-24D20:31:23.646000000..24D20:31:23.646999999], e.g.

    q)12 34 56i~`hh`uu`ss$99D12:34:56.789
  • uu$ blocked for types date, month. was previously equivalent tomm$

    q)"uu"~@[`uu$;2001.01.01,2000.01m;::]
  • in rare circumstances, writing down types 106-111 as anymap could seg-fault, e.g.

    q)`:a set enlist (+/;+\;+/:;+\:;+';+':)
    'select/exec ... by' with by clauses of dictionary type could seg-fault. now throws 'type, e.g.
    q)"type"~@[value;"select count i by b:`a`b!1 2 from ([]1 2 3)";::]

2020.11.27

Fixes and improvements

  • parallel distinct (and operations employing it, e.g. group) could seg-fault under certain conditions, e.g.

    $ q -s 256
    q)distinct 20000000#0i
  • internal multithreading (e.g. memcpy) would incorrectly be used when called from non-kdb+ threads, resulting in a deadlock.

  • mapped ragged splays would sometimes leak virtual memory, e.g. select from`:ragged/

2020.11.02

New

  • path length limit is now 4095 bytes, instead of 255.

  • os errors are now truncated (indicated by '..') on the left to retain the more important tail, e.g.

    q)get`$":root/",(250#"path/"),"file"
    '..path/path/<snip>/path/file. OS reports: No such file or directory

Fixes and improvements

  • amend/update of a vector with g attr at multiple indices is now much faster when values corresponding to one group are updated more than once, e.g.

    q)t:([]`g#50000?10);system"t:100 update x:neg x from `t where x<5"
  • upsert into a keyed table with g attr columns could be slow, e.g.

    q)n:50000;t:([k:n?10]x:`g#n?10);system"t:100 t upsert ([]k:n?100;x:n?100)"

2020.10.02

Fixes and improvements

  • functional select with a 'by' clause and malformed last argument could seg-fault. now throws 'rank, e.g.

    q)?[([]());();(1#`x)!(1#`x);(0#`)!()]
  • reserved space in anymap files is now zero-filled to ensure bitwise consistency.

    'select ... where (`p#x) in y' could seg-fault for empty x, since 2020.09.22. e.g.
    q)select from ([]`p#0#`;0#0) where x in `b`c,x1>2

2020.09.22

Fixes and improvements

```q
'select ... where (`p#x) in y' no longer ignores attribute for low counts of distinct x.
q)t:([]`p#asc 10000000?10?`3);system"t select i from t where x in 100?`3"
```
  • fills on a vector with nulls longer than 2^31 could return incorrect result, e.g.

    q)0=sum null fills((31(2*)/1)#1),0N
  • enumerating a symbol vector with nulls longer than 2^31 could return incorrect result, e.g.

    q)1=sum null`sym?`,(31(2*)/1)#`a
  • ssl ipc and https could seg-fault under on demand.

2020.08.28

New

  • removed the 255 byte limit from hsym, e.g.

    q)(":",s)~string hsym`$s:5040#"a"

Fixes and improvements

  • multicolumn search could seg-fault for certain right argument lengths.

  • in rare circumstances, loading v3.5 enums concurrently (in multithreaded input mode or peach) could result in incorrect types for the enums.

  • upper,lower,ltrim,rtrim,trim would signal 'stack when run with incorrect argument, e.g.

    q)upper(::)
    'type / previously 'stack

2020.08.10

New

  • serialise and deserialise now use multithreaded memcpy, e.g.

    q)\t system"s 10";-9!-8!100#enlist a:1000000#0
  • uncompressed file writes to shared memory/cache are now up to 2x faster, e.g.

    q)\t a:100 100000#"abc";do[100;`:/dev/shm/a set a]

Fixes and improvements

  • multicolumn search leaked memory, since 2020.07.15.

  • sums for type int now handles overflow/underflow, e.g.

    q)1 0N 0N 0N 3648 3649i~sums 1 0W 0W -0W -2147480000 1i
  • wsum for int atoms now handles overflow/underflow, e.g.

    q)0Ni~2i wsum 0W 0Wi
  • sum and prd for type int now return null on underflow, e.g.

    q)0N 0Ni~(sum -10 -0Wi;prd -1 0W 0Wi)

2020.08.03

New

  • one-shot request now checks that it has received a response message, otherwise signals 'expected response msg, e.g.

    q)`::5001"neg[.z.w]`"
    'expected response msg

Fixes and improvements

  • the partitioned query rewriter would incorrectly attempt to make use of multiprocess mode, e.g.

    $ q -s -1
    q)select count i by sym from t where date=last date,sym in`a`b
  • in rare circumstances, q could fail to return a portion of allocated memory to the OS.

  • -w counter leaked when used with negative port mode, e.g.

    $ q -w 512 -p -5001 </dev/null & q
    q)do[10;0N!`::5001"2+2"] / '-w abort

2020.07.15

New

  • errors raised by the underlying decompression routines are now properly reported as 'decompression error at block in .

Fixes and improvements

  • sending a lambda from an older version of kdb+ over ipc that no longer parses would signal 'bad lambda. e.g. from 3.6 to 4.0

    q)h{select x by x from x}
    'bad lambda {select x by x from x}
  • the built-in http server would always try to satisfy a request for accept-encoding: gzip even if zlib wasn't available, signaling 'need zlib to compress.

  • the built-in http server would always set Content-Length to uncompressed length even if using gzip.

  • improved performance and precision of xexp.

  • parse to type second was broken for precision time formats, e.g.

    q)15:35:12~"V"$"15:35:12.3456"
  • update with a dictionary as a column value now consistently throws 'type, e.g.

    q)update y:()!()from([]1 2 3)where x>1
  • improved internal parallelism in 'select ... where .. in', e.g.

    q)system"s 4";s:-80000?x:`u#-1000000?0;system"ts:10 exec i from ([]x) where x in s"
  • string representation of a view included its name since first release of 3.7t. now consistent with 3.6, e.g.

    q)value"a::b+1";"b+1"~.Q.s1`. `a
  • multicolumn search was slow for small rhs, since first release of 3.7t, e.g.

    q)t:([]0N?1000000;`);system"t:100 t?last t"

2020.06.18

New

  • allow more than one scalar to be extended in group by clause. e.g.

    q)select sum x by a:`,b:` from([]x:1 2 3)

Fixes and improvements

  • slave threads will now be referred to as secondary threads in error messages.

  • a stop error (ctrl-c or timeout) during grouping would cause a seg-fault. e.g.

    q)b:til count a:10000000?`8;
    q)select by a,b from([]a;b) / ctrl-c here
  • http client would throw 'close if the content-length header was missing from the response, since v4.0 2020.04.16.

  • upsert of a vector to an empty list on disk was erroneously throwing 'type, since v3.6 2018.11.09. e.g.

    q)`:f set();x~get`:f upsert x:til 10
  • reading an object exceeding 2GB in serialized form as part of a compound object from a single file, was throwing a 'parse error, since v3.7t 2019.10.22. e.g.

    q)get`:a set([]prd[31#2]#0x0) / threw 'parse error
  • queries on partitioned tables with by clause failed to resolve links with 'par. e.g.

    q)select a.v by b from t where date=first date
  • expressions using partition variable within the by clause returned wrong results. e.g.

    q)select v+last date by b from t where date=first date

2020.06.01

New

  • added .z.H, a low-cost method to obtain the list of active sockets.

    q).z.H~key .z.W
  • added -38!x, where x is a list of socket handles, returns a table of ([]p:protocol;f:socketFamily).

    Protocol is q (ipc) or w (websocket), socketFamily is t (tcp) or u (unix domain socket). e.g.
    q){([]h)!-38!h:.z.H}[]
    h| p f
    -| ---
    8| q u
    9| q t

2020.05.20

New

  • access-controlled file paths are now allowed to be canonical in addition to relative for remote handles under reval/-u cmd line. e.g.

    q)h(reval(value;)enlist@;(key;`$":/home/charlie/db"))

Fixes and improvements

  • = always returned false for enum atoms of different domains, e.g.

    q)(`z?`a)=`s?`a
  • the very rarely encountered 'pwuid error now includes getpwuid() return code details.

  • debug caret position was incorrect for empty application. e.g.

    q){1+1;$[;;]}[]
    q){1+1;while[]}[]
  • http requests that should result in a 404 Not Found were singalling 'type, since 4.0 2019.10.30. e.g.

    $curl 0:5000/404 # assumes q -p 5000
    \ts view::f x was equivalent to \ts view:f x (i.e. assignment instead of view definition), since first release of 3.7t.
  • improved detection of "parent dir", aka "..", in access-controlled file paths for reval/-u cmd line.

    'access error now includes associated filename if it was due to an access-controlled path. e.g.
    q)h(reval(value;)enlist@;(key;`$":/home/charlie/db/../secrets")) / throws 'access: /home/charlie/db/../secrets

2020.05.04

Fixes and improvements

  • allow lj to accept () on rhs to enable simpler upgrades for users.

  • after an http client request, or under on demand licensing, \p 0 could close a handle other than the listening port,

    and hclose h could erroneously throw 'domain, since 4.0 2020.03.30.
    -11!`:log would report badtail if the log file were appended to after the playback began, since 4.0t 2019.10.22. e.g.
    q)(h:hopen`:log set())enlist({(h:hopen`:log)enlist(`f;::);hclose h};::);hclose h;f:{n+:1;};do[3;-11!`:log];n=3
  • lambda constants were deduplicated by considering their namespace and text, but to assist the profiler in v4.0 this was removed.

    Now lambda constants are deduplicated by considering all their fields (value f), including location information.
    Thus substituted lambdas defined in .q are now deduplicated as they were prior to v4.0. e.g.
    q)value{asc;asc;{x+y};{x+y}} / asc is deduplicated, {x+y} is not
  • .h.cd was not formatting lists of char vectors correctly. e.g.

    q)("a,b,c";"foo,foo,1 2";"bar,bar,3 4";"baz,baz,5 6")~.h.cd([]a:`foo`bar`baz;b:("foo";"bar";"baz");c:(1 2;3 4;5 6))
  • view erroneously reported additional info. e.g.

    q)value"a::b+1";"b+1"~view`a

2020.04.16

New

  • exposed gzip inflate/deflate via .Q.gz. It takes a single argument x -

    for x as identity, e.g. .Q.gz[] - tests whether zlib library is loaded. Result is 0 or 1b.
    for x as a char or byte vector, unzips/inflates the vector.
    for x as 2 item list (compression level; data to compress) of (long;char|byte vector) - deflate vector with compress level -1..9.
    e.g.
    q).Q.gz{0N!count x;x}[.Q.gz(9;10000#"helloworld")]

Fixes and improvements

  • q.k - http response header "Content-Encoding: gzip" was present even if content was not zipped.

  • one-shot sync queries could corrupt the username:password field, since v4.0 2020.03.09. e.g.

    q){`::[":localhost:5000:aaaa:",x#"1";"1+1"]}each til 20; // print on remote with .z.pw:{-1 y;1b}
  • automatically removes the attribute if a list with s or u attr fails to deserialize due to [s|u]-fail error. e.g.

    q)-9!-8!`s#(2#2000.01.01;`sym?`a`b) / `sym?`a`b becomes `a`b during serialization, thereby making the list unsorted.
  • select i by ... where ... had a performance regression. e.g.

    q)t:([]til 10000000);system"ts select i:i by x from t where i=1"

2020.03.30

Fixes and improvements

  • http client was case-sensitive to http header field names. For ease of processing, all field names are now automatically converted to lowercase on reception. e.g.

    q)(`$":http://www.kx.com:80")"GET / HTTP/1.1\r\nHost: host:port\r\n\r\n"
  • update by on empty tables could erroneously return empty general list. e.g.

    q)9h=type first flip update x+1. by x1 from 0#([]1 2;3 4)
  • relaxed dup col names check with by clause for update. e.g.

    q)update count x by x mod 3 from([]til 4)
  • fixed performance regression for min. e.g.

    q)x:100000000?100;system"ts:10 min x"

2020.03.26

Fixes and improvements

  • fixed performance regression for max. e.g.

    q)x:100000000?100;system"ts:10 max x"
  • extended floor and ceiling to be identity for short type, just as it is for int and long. e.g.

    q)5 5h~(floor;ceiling)@\:5h / previously threw 'type
    
    2020.03.17 ** FIRST PRODUCTION RELEASE OF V4.0 **

2020.03.09

New

  • one-shot sync queries can now execute via `::[("host:port";timeout);query]. e.g.

    q)`::[(":localhost:5000:username:password";5000);"2+3"] // ":host:port" can also be a symbol as `:host:port
  • functions loaded via 2: reveal their (arity;bound name;shared lib name;[line number];symbol name) via get. Subject to change between versions. e.g.

    q)(3;"..f";"/home/charlie/q/m64/nvm.so";-1;"calc_mape")~get f;

Fixes and improvements

  • redirecting stdout and stderr via \1 and \2 was moving them away from the usual underlying descriptors of 1 and 2, since 3.7 2019.12.12.

    These descriptors could then become available for sockets which would then route attempts to write via 1 and 2 to those tcp handles.
  • compressed file metadata, when the file was not encrypted, was unnecessarily different to that written by 3.6. This made 'diff'ing of compressed files between versions needlessly break.

    \l was failing if the directory to load had a dot as the penultimate char in its name. e.g.
    q){@[hsym`$x;`x`y;:;0 1];system"l ",x}"/tmp/tmp.a.b";(x;y)~0 1

2020.03.05

Fixes and improvements

  • caret had wrong placement for error "'dup names for cols/groups ..". e.g.

    q){select a by a from ([]a:1 2)}[]
  • select could fail to identify all columns required in where clause on splayed/partitioned tables. e.g.

    q)([]x:1#1)~select count i from `:t/ set([]x:0 1;y:2 3) where y>2
  • upsert with both lhs and rhs as mapped nested, with `s#lhs, was seg-faulting. e.g.

    q)v set`s#(0 1;1 2);v,:v:get`:v

2020.03.02

Fixes and improvements

  • replication server was sending badly formed messages to the client for console messages logged via 0"cmd here", since v3.7 2020.02.24.

  • multithreaded distinct on type symbol could return incomplete results for large number of uniques. e.g.

    q)u:distinct v:rand[10000000]?`8;all b,:u~first{distinct x}peach 2#enlist v / with slave threads -s 2
    'select by' could seg-fault when operating on dictionaries collapsing to tables, since 3.7t 2020.02.26. e.g.
    q)([x1:1#1b]x:enlist([]a:1 2;b:2 3))~select x by x1 from([](`a`b!1 2;3;`a`b!2 3);101b)where 101b
  • functional update could seg-fault for empty or malformed expression lists, since 3.7t 2020.02.26. e.g.

    q).[!;(([] x: 1 2 3);();0b;());"type"~]

2020.02.27

Fixes and improvements

```q
'select by `s# / `p#' could seg-fault on small tables when using slave threads, since 3.7t 2020.02.26. e.g.
q)([b:til 5]a:til 5)~select max a by b from([]a:til 5;b:`p#til 5)a
```
  • select by could seg-fault on keyed tables, since 3.7t 2020.02.26. e.g.

    q)select a by b from([a:til 10];b:10?`1)

2020.02.26

NUC (Not Upwardly Compatible)

Not backward compatible. Changes existing behavior.

'select count,sum,avg,min,max,prd by' is now consistent for atoms. e.g.
q)1~first max select count 1b by x1 from ([]1 2 3;3 3 3) / was 3
  • length of by clause needs to match table count. e.g.

    q)@[value;"select k:x by 1 2 1 1 from ([]1 2 3)";"length"~]

New

  • the following primitives now make use of slave threads: _(cut), distinct, select ... by

Fixes and improvements

```q
'update by' could fail to execute the 'by' clause for empty tables. e.g.
q)@[value;"update a by 2+`a from ([]a:0#0);0b";"type"~]
```
  • when logging using -[lL] cmd line option, logging messages > 2GB resulted in a seg-fault or corrupting the log file.

  • select was leaking memory when passed a constraint of a boolean vector of an incorrect length. e.g.

    q)select from ([]())where 100000000#0b

2020.02.14

New

  • Interpret form feed (control-L) as whitespace, allowing a script to be divided into pages at logical places.

Fixes and improvements

```q
\l dir was binding data from the # and ## of anymap files into the root namespace. It now ignores files that have a trailing #.
```
  • upsert to a splayed table with out-of-order columns could have appended to the wrong column if no other error (type, rank) was detected. e.g.

    q)([]s:4 5 9 10;a:0 1 5 6;b:2 3 7 8)~select from get(`:t/ set([]s:4 5;a:0 1;b:2 3))upsert([]a:5 6;b:7 8;s:9 10)
  • set was erroneously testing for the presence of the cwd, and recreating it when missing, for a fully qualified windows path containing a disk designator. e.g.

    q)`:C:/parentdir/subdir/file set 0
  • cor was giving erroneous results as of 3.7t 2019.12.12.

  • increased the iteration count to 50000 for the key derivation via -36!. An existing master key can be converted via:

    $key=`openssl aes-256-cbc -md SHA256 -d -iter 10000 -in testkek.key`  # Prompts for existing password
    $echo $key | openssl aes-256-cbc -md SHA256 -salt -pbkdf2 -iter 50000 -out newtestkek.key  # Prompts for password
    $unset key
  • reval was not restricting file access when executed from within peach or multithreaded input mode.

2020.01.22

NUC (Not Upwardly Compatible)

Not backward compatible. Changes existing behavior.

  • extended reval to behave as if cmd line options -u 1 and -b were active, and also block all system calls which change state.

    i.e. all writes to file system are blocked, allow read access to files in pwd and below only, and no amend to globals.

New

  • current handle's TLS certificate is now available via .z.e`CERT. e.g.

    q).z.pg:{show .z.e`CERT;}
    SUBJECT       | "/C=US/ST=New York/L=Brooklyn/O=Example Brooklyn Company/CN=m..
    ISSUER        | "/C=US/ST=New York/L=Brooklyn/O=Example Brooklyn CA/CN=exampl..
    SERIALNUMBER  | "77A7E4087F283A2DD93E92F6CCB57DB6B14A7AA7"
    NOTVALIDBEFORE| "Dec 20 15:21:43 2019 GMT"
    NOTVALIDAFTER | "Dec 19 15:21:43 2020 GMT"
  • disabled ssl session cache. Was printing "error:140D9115:SSL routines:SSL_GET_PREV_SESSION:session id context uninitialized:ssl_sess.c:714".

Fixes and improvements

  • passing the same filename to \1 and \2 was causing a seg-fault on windows as of 3.7t 2019.12.12.

2019.12.12

New

  • the following primitives now make use of slave threads to execute in parallel where appropriate:

    atomics:  abs acos and asin atan ceiling cos div exp floor
    log mod neg not null or reciprocal signum sin sqrt
    tan within xbar xexp xlog + - * % & | < > = >= <= <>
    aggregate: all any avg cor cov dev max min scov sdev sum svar var wavg
    lookups:  ?(find) aj asof bin binr ij in lj uj
    for lookups, only the probe phase (i.e. dealing with the right hand side) is parallelized
    index:    @(at) select delete
    misc:     $(cast) #(take) _(drop) ,(join) deltas differ next prev sublist til where xprev
    sse-enabled primitives (mostly arithmetic) are not parallel when sse is not available (windows and nosse builds)
    within-primitive parallelism is executed similar to peach:
    \s controls the maximum number of threads
    primitives are always single-threaded within peach or negative port mode
    q)a:read1`:big.txt;st:{value"\\s ",string x;value y}
    q)f:{sum 0b>':max 0x0a0d0920=\:x};st[;"\\t:100 f a"]each 0 4 16 32 / count words
    1082 262 131 95
    as most kdb+ primitives are memory-bound, within-primitive parallelism is intended to exploit all-core memory bandwidth available on modern server hardware with multi-channel memory.
    systems with low aggregate memory bandwidth are unlikely to see an improvement for in-memory data, but on-disk data should still benefit.
    multi-threaded primitives are not NUMA-aware and should not be expected to scale beyond 1 socket.
    we recommend using 'numactl --membind=' or 'numactl --preferred=' to ensure memory access stays local and fast. see
    https://code.kx.com/q/kb/linux-production/#non-uniform-access-memory-numa-hardware
  • added support for Data-At-Rest Encryption (DARE), using aes256cbc. There are similar limitations as per compression, in terms of resource usage.

    The kdb+ admin should generate a password protected key using openssl 1.1.1, at the OS shell, as follows:
    openssl rand 32 | openssl aes-256-cbc -salt -pbkdf2 -iter 10000 -out testkek.key
    Ensure that you make a backup of the key!!! If that file is lost, you will lose access to the encrypted data.
    The key can be loaded into kdb+ using -36!(`:testkek.key;"mypassword").
    Files can be compressed and/or encrypted using the same command as for file compression, with aes256cbc encryption as algo 16. e.g.
    (`:ztest;17;2;6) set asc 10000?`3 / compress to an individual file
    (`:ztest;17;2+16;6) set asc 10000?`3 / compress and encrypt to an individual file
    or use .z.zd for process-wide default setting:
    .z.zd:17  2 6     / zlib compression
    .z.zd:17 16 6     / aes256cbc encryption only
    .z.zd:(17;2+16;6) / zlib compression, with aes256cbc encryption
    kdb+ itself needs openssl library v1.0.2 upwards, reported via (-26!)[]`SSLEAY_VERSION.
    The openssl binary needs at least v1.1.1 to generate the key, reported at the OS shell cmd line via openssl version.
    Verify that the openssl library has support for aesni (aes native instructions) via a benchmark test, comparing default vs disabled aesni support. e.g.
    with ebench.q as
    -36!(`:testkek.key;"mypassword");(`:etest;20;16;0)set 100000000?10000;system"ts max get`:etest"
    execute the default, aesni enabled if detected as
    q ebench.q
    vs aesni disabled via
    OPENSSL_ia32cap="~0x200000200000000" q ebench.q
    The performance difference between aesnon-ni and aesni is around 400%.
  • osx build no longer exits with "couldn't report -- exiting" after waking from system sleep when running under an on-demand license.

  • if \1 and \2 are given the same file, they will now share the same file table entry. This mimics the redirection

    of stdout and stderr at a unix shell "cmd > log.txt 2>&1". e.g.
    q)system each("1 log.txt";"2 log.txt")

Fixes and improvements

  • .Q.cn now uses peach to get the count of partitioned tables.

  • peach did not behave the same as each for f peach dict with an atomic dict value (used to represent a deferred map of splayed table). e.g.

    q)count peach flip t:get`:/tmp/t/ set([]0 1;2 3) / `x`x1!`:/tmp/t/
  • some system commands were silently ignoring the parameter if superfluous spaces existed between the command and the parameter. e.g.

    q)(::;2i)~system each("s  2";"s") / extra space between s and 2 resulted in it being interpreted as \s only.
  • kdb+ would enter an infinite loop when reading a response to an http request if the remote disconnected during the read.

2019.11.12

Fixes and improvements

  • to reduce the number of system calls with glibc 2.25, sorting no longer makes calls to getpid() to seed the random number generator.

  • anymap data was not being written to disk correctly. This affected 3.7t only. e.g.

    q)a~get`:tmpbytes set a:{x?0x00} each 129 250 18044 3938

2019.11.04

NUC (Not Upwardly Compatible)

Not backward compatible. Changes existing behavior.

  • lj now checks that the rhs is a keyed table. e.g.

    q)t1:([]a:1 2 3;b:10 20 30);t2:([]a:1 3;b:100 300);((1!r)~(1!t1)lj 1!t2)&((r:([]a:1 2 3;b:100 20 300))~t1 lj 1!t2)&@[t1 lj;t2;"type"~]
  • select auto-aliased colliding dup column names for either select a,a from t, or select a by c,c from t, but not for select a,a by a from t.

    Such a collision now throws a "'dup names for cols/groups a" error during parse, indicating the first column name which collides. e.g.
    q)@[parse;"select b by b from t";"dup names for cols/groups b"~]
    The easiest way to resolve this conflict is to explicitly rename columns. e.g.
    q)select a,b by c:a from t

New

  • .z.ph now calls .h.val instead of value, to allow users to interpose their own evaluation code. .h.val defaults to value.

Fixes and improvements

  • grading functions, compositions and projections was erroneous. e.g.

    q)`s#({};{}) / sometimes threw s-fail
  • added further integrity checks to streaming execute (-11!x) to avoid wsfull or seg-fault on corrupted/incomplete log files. e.g.

  • :log set();h:hopen:log;h enlist(upd;1#0xff);hclose h;:log1 1: (-5_(read1:log)),0xffffffff0000ffffff;-11!:log1 / wsfull or seg-faulted

  • appending a table to anymap was rewriting it. e.g.

    q)`:a set(`a`b!1 2;`b`c!3 4);`:a upsert(`c`d!5 6;`c`d!7 8)
  • refactored .h.hn to remain compatible with that of v3.6.

  • .z.ac generated an incorrect http response on error. e.g.

    q).z.ac:{(3;"")}
  • .Q.ft improved mem usage for scenarios where the input is modified. e.g.

    q)n:10000000;t:([a:til n]b:til n)
    q)\ts .Q.ft[{x upsert 1#t};`t] / contrived example

2019.10.22

NUC (Not Upwardly Compatible)

Not backward compatible. Changes existing behavior.

  • memory can be backed by a filesystem, allowing use of dax-enabled filesystems (e.g. AppDirect) as a non-persistent memory extension for kdb+.

  • cmd line option -m path to use the filesystem path specified as a separate memory domain. This splits every thread's heap in to two:

    domain 0: regular anonymous memory (active and used for all allocs by default)
    domain 1: filesystem-backed memory
    .m namespace is reserved for objects in domain 1, however names from other namespaces can reference them too, e.g. a:.m.a:1 2 3
    \d .m changes current domain to 1, causing it to be used by all further allocs. \d .anyotherns sets it back to 0
    .m.x:x ensures the entirety of .m.x is in the domain 1, performing a deep copy of x as needed (objects of types 100-103h,112h are not copied and remain in domain 0)
    lambdas defined in .m set current domain to 1 during execution. This will nest since other lambdas don't change domains:
    q)\d .myns
    q)g:{til x}
    q)\d .m
    q)w:{system"w"};f:{.myns.g x}
    q)\d .
    q)x:.m.f 1000000;.m.w` / x allocated in domain 1
    -120!x returns x's domain (currently 0 or 1), e.g 0 1~-120!'(1 2 3;.m.x:1 2 3)
    \w returns memory info for the current domain only:
    q)value each ("\\d .m";"\\w";"\\d .";"\\w")
    -w limit (M1/m2) is no longer thread-local, but domain-local; cmdline -w, \w set limit for domain 0
    mapped is a single global counter, same in every thread's \w
  • wj empty result had type 0 for incoming cols. e.g.

    q)(t,'([]a:0#0.;b:0#0.))~wj[-2 1+\:t.t;`s`t;t:([]s:0#`;t:0#0v;p:0#0.);(q:([]s:`a;t:0v+til 2;a:1.+til 2;b:1.+til 2);(max;`a);(min;`b))]
  • .Q.hmb now returns a 2 item list - the http header and contents. e.g.

    q)2~count .Q.hmb[`:http://www.google.com;`GET;()]

New

  • multicolumn table lookup now scales smoothly, avoiding catastrophic slowdown for particular distributions of data at the expense of best-case performance. e.g.

    q)n:3000000;t:([]`g#a:n?n;b:n?`5);q0:999?t;q1:1000?t;value each "\\t:10 t?",/:("q0";"q1")
  • added support for openssl 1.1.x.

  • http server now supports gzip compression via "Content-Encoding: gzip" for responses to form?... style requests.

    response payload must be > 2000 chars and client must indicate support via "Accept-Encoding: gzip" http header.
  • http client now supports gzip content, and .Q.hg/hp/hmb indicate this in the request via the http header "Accept-Encoding: gzip".

  • leverage s and g attr for in with nested data in the context of the first non-virtual select constraint. e.g.

    q)t:([]asc string til 1000000);system"ts select count i from t where x in enlist \"999999\""
  • added support for -11!`:fifo. e.g.

    q)`:log set ();h:hopen`:log;do[10;h enlist(`upd;10?5)];hclose h;system"gzip log;mkfifo logfifo;gunzip -c log.gz > logfifo&";upd:0N!;-11!`:logfifo
    q)system"mkfifo logfifo;gunzip log.gz > logfifo&";-11!`:logfifo
  • -u/U password file now supports sha1 password entries. Passwords must all be plain, md5, or sha1; they cannot be mixed. e.g.

    q)raze string -33!"mypassword" / -33! calculates sha1
  • any and all are now recognized as qualifying for optimization during aggregation. e.g.

    q)t:([]`p#where 100#100000;0x0);
    q)(0N!system 0N!raze@)each("ts:10 select ";;" x by x1 from t")@/:asc raze("first";"count";"avg";"last";"sum";"prd";"min";"max";"any";"all"),\:/:("";"@");
    n.b. in the example above, the trailing @ obscures the op such that it is not recognized for optimization path. e.g. max vs max@
  • anymap format writer attempts to improve page cache locality by placing small objects (<16k) first.

  • .Q.bt display highlights current frame with >>, e.g.

    q)).Q.bt`
    [2]  {x+1}
    ^
    >>[1]  {{x+1}x}
    ^
    [0]  {{x+1}x}`a
    ^
  • new debugger command &(where) to print current frame info, e.g.

    q))&
    [1]  {{x+1}x}
    ^
  • debugger restores original namespace and language (q or k) setting for every frame.

  • view calculations and system commands, including \l, correspond to individual debug stack frames.

    .d1 ).Q.bt`
    >>[3]  t0.k:8: va::-a
    ^
    [2]  t1.q:8: vb::va*3
    ^
    [1]  t1.q:7: vc::vb+2
    ^
    [0]  2+vc
    ^
  • errors thrown by 'parse' show up in .Q.trp with location information.

    q).Q.trp[parse;"2+2;+2";{1@.Q.sbt 2#y}];
    [3]  2+2;+2
    ^
    [2]  (.q.parse)
    'name (global used as local) bytecode compiler error has location info.
    q){a::1;a:1}
    'a
    [0]  {a::1;a:1}
    ^
  • -e 2 (dump stack trace) is now default for loading scripts non-interactively (e.g. with -q).

  • / internal: 2:(f;2) loads f from the binary

  • generating csv using 0: was throwing type for columns with nested vectors. .h.cd now supports these, and the delimiter used is taken from .h.d. e.g.

    q)("a,b,c";"0,a b c,1 2 3";"1,a b c,1 2 3";"2,a b c,1 2 3")~.h.cd([a:til 3]b:3 3#"abc";c:3 3#1 2 3)
  • exposed K vi(K x,UJ j) to c-api "vector[index]", which allows accessing elements of types 77..97 inclusive, akin to xK[i] for x of type 0.

    The result should be freed via r0(result) when it is no longer needed.

Fixes and improvements

  • timeout could have resulted in a different error to 'stop, e.g. 's-fail.

  • -u/U filename was detecting a filename with [0|1]filename as the single char 1. Also

    - checks supplied md5/sha1 hashes are valid hex chars
    - checks usernames are unique
    - ignores empty lines
  • -u/U and \u \U reloading password file can throw errors - "-u users not unique" and "-u bad md5/sha1 hash".

  • cmd line processing now checks for duplicate or mutually exclusive flags. e.g.

    $q -U 1 -u 1 / throws '-u or -U
  • block enabling timeout when in multithreaded input mode (cmd line -p -... option). e.g.

    @[system';("p -5000";"T 5");"can't enable timeout with -port active"~]
  • vector conditional result was erroneously retaining the g attr of the rhs false expr. e.g.

    q)`~attr ?[0011b;0;`g#0 1 2 3]
  • zip params as filenames!zipParams for file compression was not defaulting compound files (e.g. nested data) to use the same settings as the rootname. e.g.

    q)(`:splay/;`a`b`!(17 2 5;17 2 9;17 2 6))set([]a:1000 0N#1000?`4;b:asc 1000?10;c:asc 1000?10);
    q)5 5 5 9 6i~(-21!/:`$":splay/",/:("a",/:("";"#";"##")),("b";"c"))`zipLevel
  • unused bytes in enum files were not being zeroed out; this has no functional impact, it is relevant only when comparing files byte by byte. e.g.

    q)0x82d9ddf5424d4998597cf9118b893eff~md5 "c"$read1`:f set`g#`sym!0 1
  • block until async message received, h[], was not processing incoming sync requests. e.g.

    q)h:hopen 5000;neg[h]".z.w(::;::)";h[] / would cause remote to block awaiting a response message
  • ^C during each, eachleft, eachright on splays could lead to seg-fault.

  • dot with a splay as right argument previously seg-faulted, e.g.

    q)1 2 . +`a`b!`:asd/ / seg-fault
  • amend of splay failed to propagate file errors, e.g.

    q)@[`:t/ set ([]1 2;3 4);`x`x1;+;flip`a`b!`:asdasd/] / previously did set t/ to +[1 2];+[3 4]
    'asdasd/b. OS reports: No such file or directory
  • licence related errors are now reported with the prefix "licence error: ". e.g. "'licence error: upd".