Skip to content

Instantly share code, notes, and snippets.

@mavericklou
Created August 15, 2014 09:28
Show Gist options
  • Save mavericklou/adf5f714b24c821f437b to your computer and use it in GitHub Desktop.
Save mavericklou/adf5f714b24c821f437b to your computer and use it in GitHub Desktop.
I suppose #1 and #3 should be working
(ns mastermind.test.korma_test
(:use korma.core
korma.db
clojure.test))
(defn connect-database []
(let [config-map {:db "korma_test"
:user "postgres"
:password "postgres"
:host "localhost"
:port 5432}]
(default-connection (create-db (postgres config-map)))))
(defn create-table []
(exec-raw ["create table student (
id varchar primary key,
name varchar
);"])
(exec-raw ["create table course (
id varchar primary key,
name varchar
);"])
(exec-raw ["create table s_to_c (
student_id varchar references student,
course_id varchar references course
);"]))
(defn drop-table []
(exec-raw ["drop table s_to_c;"])
(exec-raw ["drop table student"])
(exec-raw ["drop table course"])
)
(declare student course)
(defentity student
(many-to-many course :s_to_c))
(defentity course
(many-to-many student :s_to_c))
(defentity sc_relation
(table :s_to_c))
(defn insert-data []
(insert student (values {:id "1" :name "John"}))
(insert student (values {:id "2" :name "Tim"}))
(insert student (values {:id "3" :name "Immo"}))
(insert course (values {:id "a" :name "Math"}))
(insert course (values {:id "b" :name "English"}))
(insert course (values {:id "c" :name "Chinese"}))
(insert sc_relation (values {:student_id "1" :course_id "a"}))
)
(use-fixtures :once (fn [f]
(connect-database)
(create-table)
(insert-data)
(f)
(drop-table)
))
(deftest test-many-to-many []
;; test case #1
(is (= (count (select student
(with course
(where {:name "Math"})))) 1) "Should this query return only one record?")
;; test case #2
(is (= (count (select student
(with course
(where {:course.name "Math"})))) 1) "Should this query return only one record?")
;; test case #3
(is (= (count (select student
(with course)
(where {:course.name "Math"}))) 1) "Should this query return only one record?"))
@immoh
Copy link

immoh commented Aug 18, 2014

It works as expected: #1 and #2 both return all students, #3 fails.

Let me clarify a bit:

(select students
  (with courses))

returns all students. In addition, for each student it fetches that student's courses with separate query and associates it to the student map.

(select students
  (with courses
    (where {:name "Math"}))

also returns all students but for each student it fetches only those student's courses that have name "Math". With this data, it returns exactly the same result as the first query. If there would be courses with other name, these would be excluded.

So with works so that it adds additional relations to the main entity. You cannot use it for restricting which students are returned.

I don't know what is your actual problem that you're trying to solve but if you need to know all math courses and their students, you can start from courses instead:

(select course 
  (with student) 
  (where {:name "Math"}))
=> ({:student ({:name "John", :id "1"}), :name "Math", :id "a"}) 

or you could use join to join students and courses on sql level:

(select student 
  (fields [:student.id :student-id] 
          [:student.name :student-name] 
          [:course.id :course-id] 
          [:course.name :course-name])
  (join course)
  (where {:course.name "Math"}))
=> ({:course-name "Math", :course-id "a", :student-name "John", :student-id "1"})

If you have a suggestion for improving the docs, pull request is welcome.

@mavericklou
Copy link
Author

Ok, from the very beginning, I regard "with" as "join" in korma. I think this is the very first feeling for join table query from docs on sqlkorma.com/docs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment