From: Justin B. <jgb...@gm...> - 2008-03-26 23:40:31
|
On Tue, Mar 25, 2008 at 2:08 PM, Bjorn Bringert <bj...@br...> wrote: > I'm thinking that it should be possible to get around this problem by > adding an explict cartesian product operator to use instead of >>= / > do. But then we are well on our way to a non-monadic interface. How does this function look: prod :: Query (Rel r) -> Query (Rel r) prod (Query qs) = Query make where make (currentAlias, currentQry) = -- Take the query to add and run it first, using the current alias as -- a seed. let (Rel otherAlias otherScheme,(newestAlias, otherQuery)) = qs (currentAlias,Empty) -- Effectively renames all columns in otherQuery to make them unique in this -- query. assoc = zip (map (fresh newestAlias) otherScheme) (map (AttrExpr . fresh otherAlias) otherScheme) -- Produce a query which is a cross product of the other query and the current query. in (Rel newestAlias otherScheme, (newestAlias + 1, times (Project assoc otherQuery) currentQry)) I modeled it after the binrel function. The long variable names reflect me trying to figure out how the state (i.e. alias) was threaded around. Continuing the example above, I can define: cmb2x = do t1 <- prod tbl1 t2 <- prod tbl2 project $ id1 << t1 ! id1 # id2 << t2 ! id2 Evaluating cmb2x gives this SQL: SELECT id13 as id1, id26 as id2 FROM (SELECT id25 as id26 FROM (SELECT COUNT(id24) as id25 FROM (SELECT id2 as id24 FROM sample_table as T1 WHERE id1 < 0) as T1) as T1) as T1, (SELECT id12 as id13 FROM (SELECT COUNT(id11) as id12 FROM (SELECT id1 as id11 FROM sample_table as T1 WHERE id1 > 0) as T1) as T1) as T2 which is far too nested. However, a one line change in mergeProject in Optimize.hs: safe :: Assoc -> Bool -- merge projections that are all aggregates or no safe assoc = not (any (isAggregate.snd) assoc) || all (isAggregate . snd) assoc aggregates gives SQL like this: SELECT id13 as id1, id26 as id2 FROM (SELECT COUNT(id2) as id26 FROM sample_table as T1 WHERE id1 < 0) as T1, (SELECT COUNT(id1) as id13 FROM sample_table as T1 WHERE id1 > 0) as T2 Which is just what I want. Justin |