Awesome, thanks. I did a little research last night looking for techniques for turning recursive queries into efficient SQL queries. I came across an interesting paper:
Cheney, James, Sam Lindley, and Philip Wadler. "Query shredding: Efficient relational evaluation of queries over nested multisets (extended version)."*arXiv preprint arXiv:1404.7078* (2014). The details are obscured behind some intimidating equations but the concept seems pretty simple: The nested query gets normalised and then shredded into a set of sql queries and the results of those queries are stitched back together. There seem to be two version <https://scholar.google.com.au/scholar?hl=en&q=Query+shredding%3A+Efficient+relational+evaluation+of+queries+over+nested+multisets+%28extended+version%29&btnG=&as_sdt=1%2C5&as_sdtp=> of the paper. This one looks to be more detailed (26 pages): https://scholar.google.com/citations?view_op=view_citation&hl=en&user=Iz-3VFQAAAAJ&sortby=pubdate&citation_for_view=Iz-3VFQAAAAJ:9pM33mqn1YgC On Monday, 29 February 2016 21:06:23 UTC+11, Krzysiek Herod wrote: > > Thanks a lot for detailed notes. > > The problem with customization of foreign keys is on my TODO list. I hope > to fix that before releasing version 1.0. That would solve the problem with > SupervisorId and AnalystId. > > What you said about deeper result structure (race -> meeting -> venue) is > very inspiring. You can't do that with this library (you can fetch records > with their - potentially indirect - relations, but those relations won't > have own relations included), but definitely it's something worth > considering. I added it to my TODO list in the README but I don't have a > clear idea about how to do it well yet. > > Cheers, > Krzysiek > > On Monday, February 29, 2016 at 12:54:31 PM UTC+8, Oliver George wrote: >> >> Oops, one more. >> >> There was also a Users table (Id, Username, ...) >> >> I didn't see a way to handle join from Races to Users based on >> SupervisorId and AnalystId. >> >> >> On Monday, 29 February 2016 15:52:48 UTC+11, Oliver George wrote: >>> >>> Thanks for the details. >>> >>> I did a little experimenting and it works as advertised. Notes below >>> show what I did and found. >>> >>> I was interested to see if this might be suitable as a simple om.next >>> remote for a relational database. Potentially fanciful but it's a topic of >>> interest for me at the moment. >>> >>> I used an existing database so I had a semi interesting dataset to play >>> with. >>> >>> Races (Id, RaceNumber, RaceTime, MeetingId, SupervisorId, AnalystId...) >>> Meetings (Id, MeetingDate, MeetingTypeId, VenueId, JurisdictionId, ...) >>> Venues (Id, Name) >>> Jurisdiction (Id, Name, Code) >>> >>> >>> The table and foreign key naming conventions didn't match so I created >>> views for each table. If that was configurable then you'd open yourself to >>> a wider audience. (e.g. MeetingId vs meetings_id) >>> >>> It was easy to setup some associations >>> >>> (def associations >>> {:meeting {:race :has-many >>> :jurisdiction :belongs-to >>> :venue :belongs-to} >>> :race {:meeting :belongs-to >>> :jurisdiction [:through :meeting :belongs-to]} >>> :venue {}}) >>> >>> My queries all worked as expected. >>> >>> (find-one db-state :meeting #{:race} [[:= :meeting.id 5617]]) >>> (find-one db-state :meeting #{:venue} [[:= :meeting.id 5617]]) >>> (find-one db-state :race #{:meeting :jurisdiction} [[:= :race.id >>> 42792]]) >>> >>> I couldn't see how I might pull data which requires three levels of >>> information (e.g. race -> meeting -> venue). I didn't dig deep enough to >>> be sure. >>> >>> Incidentally, in case you haven't come across the datomic pull inspired >>> om.next remote pull syntax this is what it might look like: >>> >>> [{:meeting [:race]}] >>> (find-one db-state :meeting #{:race} []) >>> >>> [({:meeting [:race]} [:= :meeting.id 5617])] >>> (find-one db-state :meeting #{:race} [[:= :meeting.id 5617]]) >>> >>> [{:meeting [:venue]}] >>> (find-one db-state :meeting #{:venue} [[:= :meeting.id 5617]]) >>> >>> [{:race [{:meeting [{:venue :jurisdiction}]}]}] >>> >>> Not prettier necessarily but allows for composing multiple queries into >>> a request and for drilling deeper into available data. >>> >>> cheers, Oliver >>> >>> >>> >>> >>> >>> >>> >>> On Sunday, 28 February 2016 20:02:15 UTC+11, Krzysiek Herod wrote: >>>> >>>> Thanks Oliver for the feedback, >>>> >>>> actually I came up with the idea of relational_mapper while working on >>>> a project in which I had one "data-model" that contained all the database >>>> related information, but the database related code contained a lot of >>>> features, and I really like working with small, focused clojure libraries, >>>> so in the end relational_mapper is as small as I could think of it. >>>> >>>> Also as you can see in this commit: >>>> https://github.com/netizer/relational_mapper/commit/6b4d79f92570bf723e4092d329978d484c01d2ab#diff-2b44df73d826687086fd1972295f8bd0L8 >>>> >>>> I actually was storing both: relations and fields in the same structure, >>>> but I changed that because I needed "fields" only for migrations that I >>>> used in tests, and because the whole structure was unnecessarily complex >>>> (it was much easier to make mistake modifying the fields/associations >>>> structure). >>>> >>>> Relational Mapper is meant only for reading data because whenever I >>>> tried to use complex structures to write data, I was unhappy with the >>>> result (often you have to update indexes of related records after one of >>>> them - with auto-increment field - is created, and there is a problem of >>>> determining if the related record has to be created or updated). >>>> >>>> I didn't write compare/contrast points because I couldn't find similar >>>> libraries in clojure. I mentioned ActiveRecord in README mostly because of >>>> the wording in types of relations, but even ActiveRecord is very far from >>>> Relational Mapper (it's much bigger, and has features that go way beyond >>>> simple relational mapping). >>>> >>>> Thanks again, >>>> Krzysiek >>>> >>>> On Sunday, February 28, 2016 at 10:54:57 AM UTC+8, Oliver George wrote: >>>>> >>>>> >>>>> Seems pretty nice to me. Like a light weight version of the Django's >>>>> migrate and queryset features which build on model definitions. >>>>> >>>>> It seems like this would allow me to define a database schema (tables, >>>>> relations and fields) as data and use it to both create the database and >>>>> run select/insert/update/delete queries against it. >>>>> >>>>> Is that your intention for the library? >>>>> >>>>> I've not explored the options in this space before. It might be good >>>>> to have a section in the README pointing out to other related tools with >>>>> some compare/contrast points. >>>>> >>>>> Thanks. >>>>> >>>>> >>>>> On Friday, 26 February 2016 17:51:10 UTC+11, Krzysiek Herod wrote: >>>>>> >>>>>> I created Relational Mapper, for situations where there is a >>>>>> relational database with certain amount of relations between tables and >>>>>> it's just not cool to fetch data from each table separately nor to write >>>>>> custom code for each such project so, with this library, you can just >>>>>> call: >>>>>> >>>>>> (find_all db-state :posts #{:authors :attachments} [:= post.id 1]) >>>>>> >>>>>> and assuming you have appropriate relations between these tables, you'll >>>>>> get: >>>>>> >>>>>> {:posts {:title "Christmas" >>>>>> :body "Merry Christmas!" >>>>>> :id 1 >>>>>> :authors_id 10 >>>>>> :authors {:name "Rudolf" :id 10} >>>>>> :attachments [{:name "rudolf.png" :id 100 :posts_id 1} >>>>>> {:name "santa.png" :id 101 :posts_id 1}] >>>>>> >>>>>> >>>>>> The code is here: https://github.com/netizer/relational_mapper >>>>>> >>>>>> Please, guys, let me know what do you think, and if you have any >>>>>> ideas about improvements. If somebody would be so kind to take a look at >>>>>> the code, it would be awesome to read some feedback. >>>>>> >>>>>> Krzysiek HerĂ³d >>>>>> >>>>> -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.