http://qs321.pair.com?node_id=781021

For the longest time, I've managed to limit my LDAP queries to the absolute minimum, (foo=bar), or heaven forfend, (| (foo=bar) (foo=rat)) (and it was only upon rereading that I realised I had left off the last closing parenthesis, which just goes to show how easy it is to get this wrong!)

Yesterday I had to write some really tangled queries to tease out a thousand or so records from a directory at $work. I ran into grief trying to keep my conditionals (and parentheses) nested, and concluded that it would be much better to a have a program generate the queries for me. Hence, given something like:

my $now = time; my $filter = AND( "(objectClass=dynCand)", "(candActive=TRUE)", "(dynActive=TRUE)", OR( NOT( "(candBase=EXTERNAL)" ), AND( "(candBase=EXTERNAL)", NOT( OR( "(dynProfile=ante)", "(dynProfile=catp)", "(dynProfile=fci)", "(dynProfile=mgn)", "(dynProfile=oppse)", "(dynProfile=pic)", "(dynProfile=ren)", ) ) ) ), "(candDateStart<=$now)", "(candDateEnd>=$now)", "(dynDateStart<=$now)", "(dynDateEnd>=$now)", );

The bit in the middle says "I want all the records that are internal, or if they are external, all except some profiles".

when I run the above code, it produces the fabulous:

(& (& (& (& (& (& (& (objectClass=dynCand) (candActive=TRUE)) (dynActive=TRUE)) (| (!(candBase=EXTERNAL)) (& (candBase=EXTERNAL) (!(| (| (| (| (| (| (dynProfile=ante) (dynProfile=catp)) (dynProfile=fci)) (dynProfile=mgn)) (dynProfile=oppse)) (dynProfile=pic)) (dynProfile=ren)))))) (candDateStart<=1247827075)) (candDateEnd>=1247827075)) (dynDateStart<=1247827075)) (dynDateEnd>=1247827075))

The implementation is trivial:

sub AND { return _joiner( '&', @_ ); } sub OR { return _joiner( '|', @_ ); } sub _joiner { my $op = shift; my $filter = shift; while (my $cond = shift) { $filter = "($op $filter $cond)" if defined $cond; } return $filter; } sub NOT { return "(!$_[0])"; } sub IGNORE { return; }

I threw in the IGNORE function to remove parts of the construct. Since Perl doesn't have a multi-line comment block, and you cannot embed POD within a function call, this was the easiest way to comment out a subconditional. So, if you ever need to build hairy LDAP queries, this might be for you.

• another intruder with the mooring in the heart of the Perl