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


In reply to Generating complex LDAP queries with Perl by grinder

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.