Re: A Question about (CONSTRUCT in I4GL and ISQL) Perform
Posted in 2004
Andrew Hamm wrote: > Jonathan Leffler wrote: >>There isn't any way to do this - it is a weakness of both ISQL Perform >>and I4GL CONSTRUCT statements. > > One of my cow-orkers asked about making CONSTRUCT yield a "NOT MATCHES" > clause, and there isn't syntax for it. > > I proposed passing all constructed strings through a filter function which > would (effectively) perform: > > s/ (matches ["'])!/not $1/ig > > which of course would be a fairly tedious loop in 4GL. We can also use a > script to reliably inject this call into all 4GL code since it would be > quite easy to detect the proper place. > > The nett result would be the ability of users to type: > > !A* > > then the construct would firstly treat that as a MATCHES and our function > would take over. Now that I'm thinking about it, I think this trick could be > easily applied to > > !A|B|C => NOT IN (.... > > !A:B => NOT BETWEEN ... > > Is there any chance to acually get this put into 4GL itself? Not much, but I'll lob it to the team. I suspect you'd do better talking to the Aubit4GL people, or possibly 4J's or Querix. > PS - as I scan the book for even more possible tricks - it's enticing to > allow the injection of a sub-select but that could get nasty very quickly... The one I'd really like is to enter: A*|BCD*|?[A-Z][a-z]-* and get (col MATCHES "A*" OR col MATCHES "BCD*" OR col MATCHES "?[A-Z][a-z]-*") (At the moment, the metacharacters * and ? and [...] mean that the whole string is treated as a single MATCHES expression - the OR operator has lower precedence than the metacharacters. You could combine that with negated character classes - and you'd probably want '&' too - and maybe parentheses, so that: (!A*&![CD]V*)|!(F*|BCD*) ends up as ((col NOT MATCHES "A*" AND col NOT MATCHES "[CD]V*") OR NOT (col MATCHES "F*" OR col MATCHES "BCD*")) That would be a pretty good step in the right direction. Integrating better pattern matching into the server - Perl regular expressions or something along those lines - would permit more complex expressions, but even an extension as limited as that outlined above would be a handy step up. You'd need to be able to say: 10:20|30:40 to generate "(icol between 10 and 20 or icol between 30 and 40)". Another handy trick would deal with partial DATETIME values. If dtcol is a DATETIME YEAR TO FRACTION value, then: 2001-01-01..2004-05-30 23:00 would get translated to: (dtcol between datetime(2001-01-01 00:00:00.000) year to fraction and datetime(2004-05-30 23:00:59.999) year to fraction) Note the asymmetric treatment of the missing time components depending on whether it is an upper bound or a lower bound. -- Jonathan Leffler #include <disclaimer.h> Email: jleffler@earthlink.net, jleffler@us.ibm.com Guardian of DBD::Informix v2003.04 -- http://dbi.perl.org/