""" Purpose: Efficiently Join the result of one or more queries. sadly, we seem to be utilizing dbs which have poor table design and or the db's themselves have poor support for sql. this provides the impetous for this work, which attempts to join the result of one or more result sets in a zope2x environment. gadfly contains the secret of the universe! this kinda of sucks, and its not very robust :-( restrictions: - only result sets with simple data (not enforced) - no duplicate columns other than the pivot - equal length of result sets (not enforced) Author: Kapil Thangavelu Date: 6/12/2002 CVS: $Id: $ """ from __future__ import nested_scopes import copy from Record import Record from Acquisition import Implicit from Shared.DC.ZRDB.Results import NoBrains, Results class InvalidPivotColumn(SyntaxError): pass def make_row_class(columns): class r (Record, Implicit, NoBrains): __record_schema__ = columns for k,v in Record.__dict__.items(): if k.startswith('__'): setattr(r,k,v) return r def merge_data(idx_set): """ """ lidx = 0 results = {} data = [] for idx in idx_set: keys = idx.keys() for k in keys: results.setdefault(k, []).extend(idx[k]) for k, v in results.items(): v.insert(0,k) data.append(tuple(v)) return data def construct_index(i, s): # we construct pointers to the data set # instead of going through the __getitem__ # interface of the results object d = {} for e in s: d[e[i]]=e[:i]+e[i+1:] return d def join_results(pivot, *res_set): if not pivot or not isinstance(pivot, type('')): return column_set = {} idx_set = [] col_name_set = [] for rs in res_set: names = rs.names() if pivot not in names: raise AttributeError("pivot dne in all rs") for n in names: if column_set.has_key(n) and n != pivot: raise NotImplementedError (" Duplicate Columns ") column_set[n]=None col_name_set.append(names) idx_set.append( construct_index(names.index(pivot), rs._data) ) columns = make_col(column_set.keys()) parent = res_set[0]._parent data = merge_data(idx_set) return Results( (columns, data), parent=parent) def make_col(set): cs = [] for s in set: d = {} d['name']=s cs.append(d) return cs def test(): col1 = ('name', 'color', 'food') set1 = [('mike', 'blue', 'pizza'), ('john', 'green', 'yams'), ('suzan', 'red', 'pasta')] col1 = make_col(col1) col2 = ('name', 'edu', 'state', 'age') set2 = [('mike', 'college', 'va', 21), ('john', 'high', 'ny', 22), ('suzan', 'grad', 'ut', 26)] col2 = make_col(col2) r1 = Results( (col1, set1) ) r2 = Results( (col2, set2) ) rjoin = join_results('name', r1, r2) for r in rjoin: if r.name == 'mike': assert r.edu == 'college' assert r.state == 'va' assert r.age == 21 assert r.food == 'pizza' assert r.color == 'blue' print 'works :-)'