6 emails and counting already this morning Mr spammer 8-)
Haha no problem. Nice to hear from you even if it is spam.
Another idea would be to overload the operators used in select and
extend to allow the use of rels, given that the rel has only one
attribute and is of the correct type.
Example 3:
bandicoot function:
---------------
rel Item {
id: int,
ts: long,
}
queue: Item;
rel Timestamp {
ts: long
}
fn recent(t: Timestamp): Item
{
return queue select(ts > t);
}
---------------
curl request example:
---------------
[~] echo -e "ts:long\n1312027737" | curl --data-binary @-
http://localhost:12345/recent
id:int,ts:long
[~]
---------------
In the example, it doesn't matter that the name of the attribute is
also 'ts', it only matters that the rel can be coerced into a value of
type long.
The advantage in this example is that the API is unified, and in my
mind it makes sense to use relations instead of primitive types in
both select and extend. (The case for hardcoded values in select and
extend is not something that I have used much in my short experience
with bandicoot).
Sorry for the noise: I've been playing with the original patch and I
like it a lot, so you can probably diregard my proposal. My idea was
to keep the same API for all parameters, but it may not make sense.
I would not disregard your proposal straight-away. There are a couple of things which it does not take into account though, like multiple attributes and multiple tuples (e.g. shall it evaluate each tuple comparison from the input using boolean OR or AND), etc.
Relational model defines a theta-join operator which is very similar to what you suggested and it also answers the questions above. E.g. your example could be rewritten as follows (note this is a draft syntax and bandicoot does not support this operator at the moment):
rel Item {
id: int,
ts: long,
}
queue: Item;
rel Timestamp {
ts: long
}
fn recent(t: Timestamp): Item
{
return (queue, t) join(left.ts > right.ts);
}
See here for more info: http://en.wikipedia.org/wiki/Relational_algebra#.CE.B8-join_and_equijoin
- Ostap
1.) http related:
1.1.) http 405: this error code stands for "Method Not Allowed" while this patch uses it in the following (extra) cases:
1.1.1.) number of primitive parameters does not match the function declaration
1.1.2.) primitive parameters names do not match the function declaration
1.1.3.) primitive parameters values parsing problems (more on this below)
1.2.) handling of duplicate primitive parameters; e.g. a query string "name=a&name=b&name=c" results in http 400 while this is a correct request. usually implementations return some kind of collection in this case, but its not clear what to do in case of bandicoot; it is better to ignore all but the first parameter rather than return http 400.
1.3.) http errors are not verbose enough (as it is without the patch), and now with the addition of primitive parameters the situation gets even worse; we are supposed to return entity body with the error description (this could also help to resolve 1.1)
1.4.) with the introduction of primitive parameters the following fixme becomes more of a real problem (http.c):
---
/* FIXME: we should read until '\n' or until the buffer is exhausted */
---
e.g. if a client sends a request with the primitive parameters and his/her cookies it is fairly easy to exceed the 8192 byte limit.
1.5.) primitive parameters parsing in bandicoot.c introduces another way of working with values, yet it is very similar to the pack routine (which is supposed to do exactly the same):
--- pack.c
129 int error = 0;
130 if (t == Int) {
131 v_ints[v_int_cnt] = str_int(str_vals[j], &error);
132 v[pos] = val_new_int(&v_ints[v_int_cnt++]);
133 } else if (t == Real) {
134 v_reals[v_real_cnt] = str_real(str_vals[j], &error);
135 v[pos] = val_new_real(&v_reals[v_real_cnt++]);
136 } else if (t == Long) {
137 v_longs[v_long_cnt] = str_long(str_vals[j], &error);
138 v[pos] = val_new_long(&v_longs[v_long_cnt++]);
139 } else if (t == String) {
140 error = str_len(str_vals[j]) > MAX_STRING;
141 v[pos] = val_new_str(str_vals[j]);
142 }
--- bandicoot.c (after applying the patch)
193 char *val = req->args->vals[idx];
194 int error = 0;
195 if (t == Int) {
196 arg->vals[i].v_int = str_int(val, &error);
197 } else if (t == Real)
198 arg->vals[i].v_real = str_real(val, &error);
199 else if (t == Long)
200 arg->vals[i].v_long = str_long(val, &error);
201 else if (t == String) {
202 error = str_len(val) > MAX_STRING;
203 if (!error)
204 str_cpy(arg->vals[i].v_str, val);
205 }
---
in both cases the primitive values are parsed from a string. it makes sense to unify these two to avoid code duplicity.
1.6.) http.c introduces convert() function to decode the query string parameters; this functionality is then spread between http.c and string.c:hex_to_char; it makes more sense to add just one function string.c:str_urldecode (standard name for this functionality)
1.6.1.) also, the + sign in the query string is frequently interpreted as the space character (though rfc1738 does not mention any special handling of it); probably it is alright to leave it as is with %XX only; any further comments on this?
2.) memory related:
2.1.) test/http (args_parse) has invalid reads/writes (on linux 64-bit)
2.2.) test/relation and test/transaction have memory leaks, but it looks like they were introduced with one of the previous patches
3.) misc
3.1.) Http_Args can be inlined into Http_Req => no abuse of the global name space
3.2.) there are some trailing spaces left
3.3.) Func uses very short member names while rel_param and prim_param are not inline with that; the best is to rename the rest of the members to longer names, but using something like rp and pp and comments is also alright.