Hash join: Difference between revisions

m
Line 519:
include FMS-SILib.f
 
\ Since the same join attribute, Name, occurs more than once
\ in both tables for this problem we need a hash table that
\ will accept and retrieve multiple identical keys if we want
\ an efficient solution for large tables. We make use
\ of the hash collision handling feature of class hash-table.
 
\ Subclass hash-table-m allows multiple entries with the same key.
\ After a get: hit one can inspect for additional entries with
\ the same key by using next: until false is returned.
 
:class hash-table-m <super hash-table
 
\ called within insert: method in superclass
:m (do-search): ( node hash -- idx hash false )
swap drop idx @ swap false ;m
:m next: ( -- val true | false )
last-node @ dup
if
begin
( node ) next: dup
while
dup key@: @: key-addr @ key-len @ compare 0=
if dup last-node ! val@: true exit then
repeat
then drop ; m
;class
 
\ begin hash phase
: obj ( addr len -- obj )
heap> string+ dup >r !: r> ;
 
hash-table-m rR 1 r init
s" JonahWhales " obj s" WhalesJonah" r insert:
s" JonahSpiders " obj s" SpidersJonah" r insert:
s" AlanGhosts " obj s" GhostsAlan" r insert:
s" AlanBuffy " obj s" ZombiesGlory" r insert:
s" GloryZombies " obj s" BuffyAlan" r insert:
s" Vampires " obj s" Jonah" r insert:
\ end hash phase
 
\ create Age Name table S
o{ o{ 27 'Jonah' }
o{ 18 'Alan' }
Line 534 ⟶ 565:
o{ 18 'Popeye' }
o{ 28 'Alan' } } value s
0 value str
0 value val
0 value cur
 
\ Q is a place to store the relation
: probe ( node -- ) dup val@: str =:
object-list2 Q
if cur if cr val . dup val@: p: false to cur
then space key@: p: exit
then drop ;
 
:\ join phase
\ Step through each element of list s.
: join \ { obj | list -- }
\ Probe hash-table r for hits on the Name.
0 locals| list obj |
\ For each hit show the Age and Name once, but show every Nemesis
1 obj at: @: r get: \ hash the join-attribute and search table r
: join
if \ we have a match, so concatenate and save in q
heap> object-list2 to list list q add: \ start a new sub-list in q
0 obj at: copy: list add: \ place age from list s in q
1 obj at: copy: list add: \ place join-attribute (name) from list s in q
( str-obj ) copy: list add: \ place first nemesis in q
begin
r next: \ check for more nemeses
while
( str-obj ) copy: list add: \ place next nemesis in q
repeat
then ;
 
: probe
begin
s each: \ for each tuple object in s
while
( obj ) join \ pass the object to function join
true to cur
dup 0 swap at@: to val 1 swap at: ( obj ) to str ['] probe r iterate:
repeat ;
join
s <free probe \ freeexecute the listprobe memoryfunction
 
r free2: \ free the hash-table memory
q p: \ print the saved relation
 
\ free allocated memory
s <free
r free2:
q free:
 
</lang>
{{out}}
<pre>
o{
o{ 27 'Jonah' Whales Spiders Vampires }
o{ 18 'Alan' Ghosts Zombies Ghosts}
o{ 28 'Glory' Buffy }
o{ 28 'Alan' Ghosts Zombies Ghosts} }
</pre>