How to change a namespace in a single query? - kdb

If I try to switch namespace in-place (say via qcon) to define function exactly in namespace (I want to get[`f][3;0] will give exacly the namespace in which it was defined), I got empy result - it seems like no namespace switching occured:
\d .
system"d .ns1"; f1:{x+y}; get[.ns1.f1][3;0]~`
but:
\d .
system"d .ns1"; // notice the only difference is the newline
f1:{x+y}; get[.ns1.f1][3;0]~`ns1
Is it a bug of 3.6 32bit version? or a feature?
If it is a feature, then how to switch to new namespace in a single qcon query?

A code line is evaluated in the context before the code line is executed. Therefore, f1's definition in the first sample was evaluated in the context before namespace switching occurred.

Related

kdb: can I use the set keyword to achieve #[`.;`upd;:;.some.function]?

Say there's an existing function definition .my.func:{[tbl;data] ...} and I want to set the upd function to this lambda.
Are the two lines below equivalent?
#[`.;`upd;:;.my.func]; / #1
`upd set .my.func; / #2
Asking because I see a lot of #1 in the codebase I work with, but #2 seems more succinct, so was wondering if they're somehow different.
I checked https://code.kx.com/q/ref/amend/
"Amend at" #[d; i; v; vy]
This seems to simply define the function upd in the global namespace.
d = `.
i = `upd
v = :
vy = .my.func
After running #1/#2 myself, get`. also seems to suggest #1/2 are equivalent.
The lines are not equivalent in the scenario where \d is used to change namespace. In the examples above set creates the variable in the current namespace and this happens to be the global namespace. # creates the variable in the global namespace.
Example for set using .test namespace creates .test.upd instead.
d).my.func:{x}
q)\d .test
q.test)`upd set .my.func;
q.test)upd
{x}
q.test)\d .
q)upd / upd does not exist in global namespace
'upd
[0] upd
^
q).test.upd / upd exists in .test namespace
{x}
Example for # using upd2 to highlight differences to upd example above. upd2 is created in the global namespace.
q)\d .test
q.test)#[`.;`upd2;:;.my.func];
q.test)upd2 / upd2 does not exist in .test namespace
'upd2
[0] upd2
^
q.test)\d .
q)upd2 / upd2 exists in global namespace
{x}
Following on from Thomas' answer, it's also helpful to know that you can use # to create your function in the current namespace also. The d system command, without an argument, will return the current namespace, and you can use this as the first parameter to #.
q).my.func:{x}
q)\d .test
q.test)\d
`.test
q.test)system"d"
`.test
q.test)#[system"d";`upd;:;.my.func]
`.test
q.test)upd
{x}
Note that this method will only work once the namespace has been initialized first, i.e. something else must exist in the namespace, otherwise you'll see a 'type error.
q)key`
`q`Q`h`o`test
q)\d .new
q.new)#[system"d";`upd;:;.my.func]
'type
q.new)type each(.new;.test)
0 99h
Asking because I see a lot of #1 in the codebase I work with, but #2 seems more succinct, so was wondering if they're somehow different.
You can still use set to assign a value to a variable in the global namespace regardless of a namespace you're currently in, you just need to be a bit more explicit:
q)`upd set .my.func / sets upd in the current namespace
q)`..upd set .my.func / sets upd in the global namespace
q)\d .test
q.test)`upd set {x+1}
`upd
q.test)`..upd set {x+42}
`..upd
q.test)upd
{x+1}
q.test)\d .
q)upd
{x+42}

Drools filtering stream within DRL

I would like to create a rule with lamba expression like below:
when
rule_id: String() from "784acba8-32e5-41de-bd73-04f9ce2bfaff"
$: DroolsEventWrapper(Arrays.stream("testing".split("")).filter(element->(element!=null && element.contains("e"))).findFirst().isPresent())
then
System.out.println("Qualified for "+rule_id);
end
just a simple check "testing" will be given as a parameter also; however when I use it drl. It gave error like:
mismatched input '.' in rule "784acba8-32e5-41de-bd73-04f9ce2bfaff" in pattern
When I check the location of that dot; it belongs to filter(element->(element!=null && element.contains("e"))) when I omit it, it is working.
I am using the latest version of Drools: 7.55.0.Final. I found some tickets which say that lambda expressions somehow buggy at previous versions but not the latest ones.
Do I missing something, or is there any way to run this within DRL ?

Grafana (V7) adding variable in table name

I need to be able to use variables in table names - I basically have the same set of tables used for different types of data, so I would like to just have one dashboard and swapping between all types instead of always having to set up multiple identical dashboards.
My query is something like:
select * from table_$variable_name;
Where my list of possible variable is something like cat, dog, bird
I can seem to make this work, if I only put the variable as shown above I get the following error
Error 1146: Table 'table_$variable_name' doesn't exist
If I enclose it in curly brackets, I get this error instead.
Error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '{bird}' at line 1
(i.e. with the selected variable actually being visible this time)
I'm not sure if the issue is having underscores in the table names, I tried putting underscores around my variables too to check and I had no luck with that.
Another thing I tried was gradually adding on to the table name, so e.g.
select * from table_$variable;
Still returns an error, but I can see the table name starting to form correctly
Error 1146: Table 'table_bird_' doesn't exist
However, as soon as I add another underscore, the variable is not picked up abymore
```Error 1146: Table 'table_$variable_' doesn't exist``
I'm sure it's something silly I am missing in the syntax of the query - anyone has any suggestions?
Using this https://grafana.com/docs/grafana/latest/variables/templates-and-variables/ for reference
As #arturomp suggests, use
${var:raw}
At least in my case, this was the solution that worked.
I found double square brackets work. e.g.
Rather than
select * from table_$variable_name;
use
select * from table_[[variable_name]];

Grafana: Overrriding series with metric named `/var(avail_MB)`: "Panel rendering error '/var(avail_MB)' is not a valid regular expression."

An Icinga2 plugin (written by myself) returns performance data with metrics named /var(avail_MB), /var(total_MB) and similar. Data is forwarded to an InfluxDB with Grafana as Frontend.
I'm using "GROUP BY" "tag(metric)" and "ALIAS BY" "$tag_metric" in a dashboard's panel query.
The metric names are displayed correctly below the graph then.
However when I try to override series by specifying "alias or regex" /var(avail_MB) it does not seem to work, and when going back from panel configuration to dashboard, I get an error message saying "Panel rendering error '/var(avail_MB)' is not a valid regular expression.".
I tried to put a backslash in front of ( and ), but that didn't help.
To make matters worse, the whole graph disappeared, and when trying to open the "Query Inspector", the frontend seems to take forever (Query never appears).
What is the problem, and how could I fix it?
I'm new to Icinga2, Grafana and InfluxDB (I'm just a "user" not administrator of those).
The color change is not applied to the graph.
Here is an example of plugin output:
OK: /var: 3114/5632MB (55.30%), slope is NaN|/var(total_MB)=5631.56MB;;;0 /var(avail_pct)=55.30%;25;5;0;100 /var(avail_MB)=3114.12MB;10;5;0;5632 /var(est_avail_MB)=nanMB;10;5;0;5632
(The "nanMB" was a bug in the plugin that has been fixed already, but that data wasn't from the machine in question.)
The problems seems to be the beginning of the string ("/var").
Grafana seems to treat every string starting with / as regular expression, and it expects any regular expression to start with /, too (it seems).
So the fix was to add a trailing /, and escape the literal / as \/.
Unfortunately this only removes the error message, but doesn't make the override work (match).
It is also required to backslash-escape the parentheses and the slash(es):
Instead of /var(total_MB) you need to write /\/var\(total_MB\).
The original problem has two origins:
The monitoring plugin specification at https://www.monitoring-plugins.org/doc/guidelines.html#AEN201 states: "2. label can contain any characters except the equals sign or single quote (')") states that any character except = and ' is allowed as metric name.
Grafana v6.7.3 proposes the incorrect (i.e.: unescaped) values for "alias or regex".
That is how I had created the problem.

Why is this xmlns attribute messing up my xpath query?

I'm parsing a simple jhove output using LibXML. However, I don't get the values I expect. Here's the code:
use feature "say";
use XML::LibXML;
my $PRSR = XML::LibXML->new();
my $xs=<DATA>;
say $xs;
my $t1 = $PRSR->load_xml(string => $xs);
say "1:" . $t1->findvalue('//date');
$xs=<DATA>;
say $xs;
$t1 = $PRSR->load_xml(string => $xs);
say "2:" . $t1->findvalue('//date');
__DATA__
<jhove xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://hul.harvard.edu/ois/xml/ns/jhove" xsi:schemaLocation="http://hul.harvard.edu/ois/xml/ns/jhove http://hul.harvard.edu/ois/xml/xsd/jhove/1.3/jhove.xsd" name="Jhove" release="1.0 (beta 3)" date="2005-02-04"><date>2006-10-06T09:11:34+02:00</date></jhove>
<jhove><date>2006-10-06T09:11:34+02:00</date></jhove>
As you can see, the line "1:" is returning an empty string, while "2:" is returning the expected date. What is in the jhove-root-element that keeps the xpath query from working properly? I even tried in XML-Spy and there it works, even with the full header.
Edit: When I remove the xmlns-attribute from the root element, the xpath query works. But how is that possible?
The XML::LibXML::Node documentation specifically mentions this issue and how to deal with it...
NOTE ON NAMESPACES AND XPATH:
A common mistake about XPath is to assume that node tests consisting of an element name with no prefix match elements in the default namespace. This assumption is wrong - by XPath specification, such node tests can only match elements that are in no (i.e. null) namespace.
So, for example, one cannot match the root element of an XHTML document with $node->find('/html') since '/html' would only match if the root element <html> had no namespace, but all XHTML elements belong to the namespace http://www.w3.org/1999/xhtml. (Note that xmlns="..." namespace declarations can also be specified in a DTD, which makes the situation even worse, since the XML document looks as if there was no default namespace).
There are several possible ways to deal with namespaces in XPath:
The recommended way is to use the XML::LibXML::XPathContext module to define an explicit context for XPath evaluation, in which a document independent prefix-to-namespace mapping can be defined. For example:
my $xpc = XML::LibXML::XPathContext->new;
$xpc->registerNs('x', 'http://www.w3.org/1999/xhtml');
$xpc->find('/x:html',$node);
Another possibility is to use prefixes declared in the queried document (if known). If the document declares a prefix for the namespace in question (and the context node is in the scope of the declaration), XML::LibXML allows you to use the prefix in the XPath expression, e.g.:
$node->find('/x:html');
I found another solution. Simply using this
say "1:" . $t1->findvalue('//*[local-name()="date"]');
will also find the value and save the hassle of declaring namespaces in an XPathContext. But apart from that, tobyinks answer is the correct one.