diff --git a/README b/README deleted file mode 100644 index c52d6a0..0000000 --- a/README +++ /dev/null @@ -1,149 +0,0 @@ -h1. Relational Algebra for Clojure - -h2. Description - -Implementation of the relational operators: project, select (restrict), -rename, crossproduct, various joins, union, difference and intersection. - -See example code at the bottom of hoeck/rel/reflection.clj - -To use it in clojure, include this directiory to your -classpath and then simply type (use 'hoeck.rel.reflection). - -Needs also some -"clojure.contrib":http://code.google.com/p/clojure-contrib/ modules -and "lazymap":http://bitbucket.org/kotarak/lazymap from kotarak. - -h2. Some examples using the reflection relations - -* Load the hoeck.rel library -
-
-user> (use 'hoeck.rel.reflection)
-
-
- -* Print all accessible relations in a map rel-name -> fields -
-
-user> (with-relations (pprint (into {} (field-map (relations) :relation :field))))
-{:publics (:ns :name :varname),
- :namespace (:name),
- :interfaces (:class :interface),
- :methods (:returntype :returns-array :modifiers :arity :class :name),
- :imports (:ns :class :name),
- :jars (:jar :time :compressed-size :path :comment :name :directory :size),
- :interns (:ns :name :varname),
- :classpaths (:path),
- :files (:time :path :name :directory :size),
- :method-args (:arity :position :class :method :type),
- :classes (:super :class :type :modifiers),
- :refers (:ns :name :varname),
- :aliases (:ns :name :alias)}
-
-
- -* Private definitions in the hoeck.rel.reflection namespace -
-
-user> (with-relations (project (select (difference :interns :publics)
-                                       (= ~ns 'hoeck.rel.reflection))
-                               :name))
-#{{:name classnames-from-ns   }
-  {:name method-args          }
-  {:name class-interfaces     }
-  {:name path->package        }
-  {:name read-files-from-jar  }
-  {:name class-methods        }
-  {:name without-dotclass     }
-  {:name classnames-from-files}
-  {:name class-tuple          }
-  {:name find-classnames      }
-  {:name classnames-from-jars }}
-
-
- -* Relation of all files on the classpath, ordered by size -
-
-user> (with-relations
-       (order-by
-        (project :files [(/ ~size 1000.0) :size-in-kb] :name :path)
-        :size-in-kb
-        '>))
-#{{:size-in-kb  43800.36, :name "rt.jar",       :path "C:\\Programme\\Java\\jre6\\lib"}
-  {:size-in-kb  6592.915, :name "charsets.jar", :path "C:\\Programme\\Java\\jre6\\lib"}
-  ...}
-
-
- -* Relations are first-class citizens -
-
-user> (with-relations (def java-lang-classes (select :classes (rlike "^java\\.lang\\.[A-Z].*" ~class))))
-#'hoeck.rel.reflection/java-lang-classes
-
-user> (defn without-inner-classes [classes-rel]
-        (select classes-rel (rlike "[^\\$]*" ~class)))
-#'hoeck.rel.reflection/without-inner-classes
-
-
- -* The number of classes in the java.lang package -
-
-user> (count (without-inner-classes java-lang-classes))
-108
-
-
- -* All inner classes in the java.lang package -(takes some time to compute, calculates all indexes over the :classes relation due to my poor difference implementation) -
-
-user> (count (difference java-lang-classes (without-inner-classes java-lang-classes)))
-48
-
-
- -* Number of implemented interfaces -
-
-user> (with-relations (count (project :interfaces :interface)))
-2035
-
-
- -* Total number of interfaces -
-
-user> (with-relations (count (select :classes (= ~type :interface))))
-2580
-
-
- -* Classes (directly) implementing clojure.lang.IFn -
-
-user> (with-relations (-> (select :interfaces 
-                                  (= 'clojure.lang.IFn ~interface))
-                          (field-seq :class)
-                          (pprint)))
-(hoeck.mapped_map.MappedMap
- hoeck.magicmap.MagicMap
- clojure.lang.AFn
- clojure.lang.Keyword
- clojure.lang.Ref
- clojure.lang.Var)
-
-
- -h2. TODO - -* ant build script -* function-join -* datalog (iris and/or clojure.contrib.datalog) -* sql backend -* index-aware select -* more index types: sorted-index, none -* other backends, query-by-example, constraints, query-compiler diff --git a/README.textile b/README.textile index f52d834..12146c4 100644 --- a/README.textile +++ b/README.textile @@ -25,15 +25,12 @@ Include the generated rel.jar in your classpath h2. Some examples using the reflection relations * Load the hoeck.rel library -
-
+

 user> (use 'hoeck.rel.reflection)
-
-
+
* Print all accessible relations in a map rel-name -> fields -
-
+

 user> (with-relations (pprint (into {} (field-map (relations) :relation :field))))
 {:publics (:ns :name :varname),
  :namespace (:name),
@@ -48,12 +45,10 @@ user> (with-relations (pprint (into {} (field-map (relations) :relation :field))
  :classes (:super :class :type :modifiers),
  :refers (:ns :name :varname),
  :aliases (:ns :name :alias)}
-
-
+
* Private definitions in the hoeck.rel.reflection namespace -
-
+

 user> (with-relations (project (select (difference :interns :publics)
                                        (= ~ns 'hoeck.rel.reflection))
                                :name))
@@ -68,12 +63,10 @@ user> (with-relations (project (select (difference :interns :publics)
   {:name class-tuple          }
   {:name find-classnames      }
   {:name classnames-from-jars }}
-
-
+
* Relation of all files on the classpath, ordered by size -
-
+

 user> (with-relations
        (order-by
         (project :files [(/ ~size 1000.0) :size-in-kb] :name :path)
@@ -82,57 +75,45 @@ user> (with-relations
 #{{:size-in-kb  43800.36, :name "rt.jar",       :path "C:\\Programme\\Java\\jre6\\lib"}
   {:size-in-kb  6592.915, :name "charsets.jar", :path "C:\\Programme\\Java\\jre6\\lib"}
   ...}
-
-
+
* Relations are first-class citizens -
-
+

 user> (with-relations (def java-lang-classes (select :classes (rlike "^java\\.lang\\.[A-Z].*" ~class))))
 #'hoeck.rel.reflection/java-lang-classes
 
 user> (defn without-inner-classes [classes-rel]
         (select classes-rel (rlike "[^\\$]*" ~class)))
 #'hoeck.rel.reflection/without-inner-classes
-
-
+
* The number of classes in the java.lang package -
-
+

 user> (count (without-inner-classes java-lang-classes))
 108
-
-
+
* All inner classes in the java.lang package (takes some time to compute, calculates all indexes over the :classes relation due to my poor difference implementation) -
-
+

 user> (count (difference java-lang-classes (without-inner-classes java-lang-classes)))
 48
-
-
+
* Number of implemented interfaces -
-
+

 user> (with-relations (count (project :interfaces :interface)))
 2035
-
-
+
* Total number of interfaces -
-
+

 user> (with-relations (count (select :classes (= ~type :interface))))
 2580
-
-
+
* Classes (directly) implementing clojure.lang.IFn -
-
+

 user> (with-relations (-> (select :interfaces 
                                   (= 'clojure.lang.IFn ~interface))
                           (field-seq :class)
@@ -143,8 +124,7 @@ user> (with-relations (-> (select :interfaces
  clojure.lang.Keyword
  clojure.lang.Ref
  clojure.lang.Var)
-
-
+
h2. TODO: diff --git a/hoeck/rel/operators.clj b/hoeck/rel/operators.clj index 399564c..9550259 100644 --- a/hoeck/rel/operators.clj +++ b/hoeck/rel/operators.clj @@ -56,6 +56,7 @@ (defmulti join join-dispatch) ;; natural-join (defmulti outer-join join-dispatch) ;; right-outer-join (defmulti full-outer-join join-dispatch) +(defmulti fjoin op-dispatch-fn) ;; m (defmulti union two-op-dispatch-fn) (defmulti difference two-op-dispatch-fn) diff --git a/hoeck/rel/structmaps.clj b/hoeck/rel/structmaps.clj index 8504d4f..3225907 100644 --- a/hoeck/rel/structmaps.clj +++ b/hoeck/rel/structmaps.clj @@ -52,7 +52,6 @@ (next keys))) ret))) - ;; index tools (defn- index-lookup @@ -355,6 +354,8 @@ (magic-map a (fn ([] (keys b)) ([k] (get b k))))) +;;; joins + (defmethod join :clojure [R r S s] (let [index-Ss (find (index S) s) join-tuple (fn [r-tup] (let [friends (get (val index-Ss) (r-tup r))] @@ -375,6 +376,14 @@ (is (= (set (fields j)) (set (concat (fields R) (filter #(not= :id %) (fields S))))) "joined fields") (is (= (clean-index (index j)) (make-index j (fields j))) "index")))) +(defmethod fjoin [R f] ;; much like project with an expression, but allows 1..n joins instead of 1..1 only + ;; f must return a seq of tuples or nil + (let [] + (Relation (merge ^R {:fields (fields R) ()}) {} + {'seq _ + 'get _ + 'count _}))) + (defmethod xproduct :clojure [R S] (let [cross-tuple (fn [r-tup] (map #(merge r-tup %) S))] (Relation. (merge ^S ^R {:fields (concat (fields R) (fields S))