zgemba has asked for the wisdom of the Perl Monks concerning the following question:

I need a small and simple SQL like thingy to search in memory. My data structure is just hash of hashes {id} {key_n} {value}
I'd like to:
SELECT id WHERE ( (key1 IS "foo") AND (key2 IS "bar)) OR (key4 < 10)
or somethung like this.
One problem is, that some records do not have all the keys.
I thought about hacking apart Sprite.pm but I'm not quite up to it yet.

Replies are listed 'Best First'.
Re: Simple SQL like thingy?
by htoug (Deacon) on Jun 19, 2002 at 09:33 UTC
    Try looking at DBD::RAM, it should be able to do what you want with a little tweaking.
Re: Simple SQL like thingy?
by zejames (Hermit) on Jun 19, 2002 at 07:47 UTC
    Hello ,


    This is one of the ways to do it :
    foreach $id (keys %hashes) { push @ids, $id if ( cond($hashes{$id}) ); } sub cond { my %line = %{shift}; return ( ( ($line{'key1'} eq "foo") and ($line{'key1'} eq "bar") ) or ($hashes{$id}{'key4'} < 10) ); }
    Then @ids contains all the ids that correspond to your request.

    HTH

    Update: made the code cleaner

    --
    zejames
Re: Simple SQL like thingy?
by Zaxo (Archbishop) on Jun 19, 2002 at 08:04 UTC

    Your question is a little oddly put, so I can't be sure I'm answering what you asked. If you want to do a database-like selection of keys from a hash, grep is probably the best way to support the logic:

    #assumes %the_hash{'this_id'} = { key1=>'quux', key4=>12 } and so on my @selected_id_keys = grep { ( exists $the_hash{$_}{'key1'} and $the_hash{$_}{'key1'} eq 'foo') and ( exists $the_hash{$_}{'key2'} and $the_hash{$_}{'key2'} eq 'bar') or ( exists $the_hash{$_}{'key4'} and $the_hash{$_}{'key4'} < 10) } keys %the_hash;
    You want to check existance of the key before testing values, so as to avoid autovivifying a key that's not present. The parens in the logic are for human eyes, they do not affect evaluation in this case.

    After Compline,
    Zaxo

Re: Simple SQL like thingy?
by Beatnik (Parson) on Jun 19, 2002 at 08:00 UTC
    my %HoH = (); #Something my @IDs = (); my ($key,$value); while( ($key,$value) = each(%HoH) ) { push(@IDs,$key) if ($HoH{$key}{key1} eq "foo" && $HoH{$key}{key2} e +q "bar") || $HoH{$key}{key4} < 10; }
    Just a guess...

    Greetz
    Beatnik
    Perl is like sex: if you're doing it wrong, there's no fun to it.
Re: Simple SQL like thingy?
by Anonymous Monk on Jun 19, 2002 at 08:35 UTC
    I guess I was not clear enough with my question.
    I need to parse a text line containing the query (in SQL syntax) and then search my data structure.
    The query is pretty much standard SQL, limited to one table (no joins), but possibly with many conditions.
    I hope it's clearer now?

      Have you taken a look at DBD::AnyData (alt.)?

      I don't recall it supporting hashes "out of the box", but some fancy map'ing or adapting the existing ARRAY backend (the module has an open API for adding your own formats) should get you to where you want to be.

          --k.


Re: Simple SQL like thingy?
by Revelation (Deacon) on Jun 19, 2002 at 19:00 UTC
    I would be inclined to cache results for as long as I deemed necessary, and use the Cache::FileCache module to retrieve that large hash we have.

    use Cache::FileCache; my $cache = new Cache::FileCache( ); my $hash = $cache->get( $assigned_hash_name ); my %hash = %{$hash};
    To edit the hash, all we would have to do is reset the cache to the new hash(ref), and to delete it all we have to do is:  $cache->Purge( )

    We can then grep using Zaxo's code, or we could devise our own.

    Notice: Code has not been tried, and is liable to break down at any time, and is probably not the best course of action.
    Gyan Kapur
    gyan.kapur@rhhllp.com
      "Code has not been tried..." etc. Thank God. Do you really think we Perlmonks are THAT stupid?! -100104
Re: Simple SQL like thingy?
by smackdab (Pilgrim) on Jun 19, 2002 at 17:48 UTC
    I might be totally wrong...and it probably depends upon how you handle missing keys...if id and key_n form the compound unique index...then this might be useful (is in my case ;-)
    {id} {key_1} = {value} {id} {""} = {value} {id} {key_2} = {value} {""} {key_1} = {value} {""} {key_2} = {value}