Context

Hi,

I have to load data and functions into a specific context, not in default one.

In queries are not working as it is not able to find the nested tables in the context. Following is a demo tables and configuration.

  1. TestDataScript.q

;AddFun:{x+y}

;SubFun:{x-y}

;MultiFun:{AddFun[x;y]+SubFun[x;y]}

;t:( a:100?01b;b:100?01b;c:100?01b;d:100?1f) 

;t1:( a:100?01b;b:100?01b;c:100?01b;d:100?1f) 

;CallTable:{select from t where not a in(exec a from t1 where b=x)}

;CallTable1:{select from t where a =x}

  1. LoadScript.q

\d .Account1

\l Scripts\TestDataScript.q

\d .

  1. From the q prompt i call

\l LoadScript.q

So it creates all the above function and tables in Account1 context

Following functions work fine:

.Account1.AddFun[2;3]

.Account1.MultiFun[2;3]

.Account1.CallTable1[0b]

Except these one:

.Account1.CallTable[1b]

Error: t1

.Account1.CallTable[0b]

Error: t1

Any idea what i am doing wrong?

I changed the function CallTable by following:

;CallTable:{select from t where not a in(exec a from .Account1.t1 where b=x)}

and it works but i dont want to add name spaces in inner code.

Even i tried functional form

;CallTable3:{fact:parse “select from t where not a in(exec a from t1 where b=x)”

;?[t;raze fact 2; 0b;fact 4]}

it don’t work. Unless i add .Account1 namespace like following:

;CallTable4:{fact:parse “select from t where not a in(exec a from .Account1.t1 where b=x)”

;?[t;raze fact 2; 0b;fact 4]}

Hi Vikas,

you can see the dependencies of a function using value

http://code.kx.com/wiki/Reference/value

e.g.

q)value .Account1.CallTable

0x0ba0a181a20a040005

,`x

`symbol$()

Account1t

0b

,(~:;(in;a;(?;t1;,(=;b;x);();,`a)))

?

“{select from t where not a in(exec a from t1 where b=x)}”

from which you can see it is aware of the global t in Account1. It looks up t1 dynamically from the root namespace.

To avoid that you could do

q.Account1)CallTable:{b:exec a from t1 where b=x;select from t where not a in b}

q.Account1)value CallTable

0xa00ba181a20a040316020ba3a482a20a040006

,`x

,`b

Account1t1`t

`a

,(=;b;x)

?

0b

,(~:;(in;a;b))

“{b:exec a from t1 where b=x;select from t where not a in b}”

or

CallTable:{t2:t1;select from t where not a in exec a from t2 where b=x}

BUT - in general, we recommend to use namespaces for functions only, and put tables/data in the root namespace. This is partly reflected in that .z.vs notifies of changes in root namespace only.

thanks

Thanks.

So Is this the issue from Q side that it takes from the root namespace?

Currently we cannot move tables in root namespaces as per the requirement. Data tables must be separate into different namespaces. Other than In Queries do we have to take care of some other things?

Thanks.

So Is this the issue from Q side that it takes from the root namespace?

Currently we cannot move tables in root namespaces as per the requirement. Data tables must be separate into different namespaces. Other than In Queries do we have to take care of some other things?

It can recognize t as a global at compile time, but not t1. At runtime, it discovers t1 is not a field of t, is not a local var, and tries to resolve it in the current working namespace - not the namespace that it was compiled in. If you set your working namespace to .Account1 and then execute your function, you should find it runs ok.

Thanks Charles, i understood that part. Is there any way i can specify the current workspace through IPC, I am using C# as client?

yes, if you do something along the lines of

With

q)h:hopen 5000

q)h “\d .a other stuff here”

everything appearing after the a is ignored.

but the context can be changed for the duration of the call, e.g.

q)h ({value"\d .a";b set x;get.a.b};10)
10

or

h “{value"\\d .a";};b:5”

Thanks Charles. It worked fine. i created a function like following.

globalFunCall:{[myContext;query]

value “\d .”, myContext;value query}

globalFunCall[“Account1”;“CallTable[0b]”]

globalFunCall[“Account2”;“CallTable[1b]”]

I know its a different question but though its related to context. i raised one question earlier related to logging and implemented same as given in:

http://code.kx.com/wiki/Cookbook/Logging

How to log Namespace related data and load when q start, just using -l commands logs data only for default namespace?

yes, you’re right that logging only logs commands which set the root global state - similar to .z.vs, as I mentoned before.

Hence through setting the global root var a here it logs that full command

$ q logTest -l

KDB+ 3.2t 2014.07.28 Copyright (C) 1993-2014 Kx Systems

m64/ 4()core

q)0({a set 0;value"\\d .test";b set 5;value"\d ."};::)

q).test.b

5

q)\

$ q logTest -l

KDB+ 3.2t 2014.07.28 Copyright (C) 1993-2014 Kx Systems

m64/ 4()core

q).test.b

5

q)\

n.b. you’ll need to reset the namespace at function end. I don’t think this is a particularly good way to progress though (data in namespaces).

Thanks Charles. We are trying to use multiple data namespaces because of our internal existing environments. we cannot club different environments data into single table with a column that defines record belong to which namespace(environment). 
Can you please suggest some other alternatives, looks like it may be more complex if we keep on going same path. 

Not sure if we can have multiple q instances running with a single license on same box,

I end up couple of issues with context:

  1. Above solution works only for 1 q restarts. So if we restart q again. .test namespace was gone.

  2. Enums are also not working for me, it gives type error

.test.x:abc

{value “\d .test”;value “.test.x$a”} / Works but we cannot use specific namespace inside another function

{value “\d .test”;value “x$a”}   /Dont work, it wont work because it tries to search x into global root namespace

{value “\d .test”;value “x”}  / works, it is able to find x in test namespace

{value “\d .test”;value “x$`a”}  / dont work

regarding licensing, you can run multiple kdb+ processes on your licensed cores

btw, something that is often overlooked is storing tables in root namespace inside a dict, e.g.

q)env.1.t:(a:0 1)

q)env.2.t:(a:2 3)

note this does not have a leading .

Actually i wanted to do minimum changes to existing functions that internally called direct tables. Using context would have been easy but with the above complexity involved, i will end up changing existing functions to accept a environment(context) variable and use following way for each environment in root namespace.