This post originated from an RSS feed registered with Agile Buzz
by James Robertson.
Original Post: REO
Feed Title: Michael Lucas-Smith
Feed URL: http://www.michaellucassmith.com/site.atom
Feed Description: Smalltalk and my misinterpretations of life
I've come in 8 minutes late - oops! Missed breakfast. I'm feeling alive though right now so I'm just running late, not hung over :)
Existing queries are typical SQL: SELECT a FROM table WHERE ...
Avi has mapped SQL 'algebra' in to Smalltalk classes so that building a query is done just by building objects, not by constructing a bunch of text together.
The act of iterating causes real information to be pulled from the database.
One SELECT figures out what columns exist in the table. From then on it knows and it selects out the attributes for the iteration. A small select at the start, barely a cost.
SELECT "students" AS c1, "name" AS c2 FROM students
The query optimiser makes the ugly selects work as fast as a nicer looking select.
range := students copyFrom: 5 to: 10
At this point, there has been no select. It holds a range on a relationship.
range asArray
Turning it in to an Array causes it to do the actual select which limits the select to the 5 results.
The trade off between object-relational framework with its cache vs arbitrary adhoc queries that can be optimised.
Again, inspecting that doesn't do any kind of query yet. It's an RASelection. Not until its iterated does it do the actual query.
Question: Can a selection have another selection?
a) select2 := select: :ea | ea studentNumber < 7 - it gets uglier and uglier, assuming the database will optimise these queries.
The select trick is doing the same trick that glorp does, using a proxy object in to the blocks to figure out what to actually send. An old Toplink trick.
Why is this useful? This allows you to factor your code a lot better. Each little bit of code doesn't need to know what it's starting with, it just adds its rules. Using SQL you cannot concatenate SQL strings and get something meaningful or even working.
This framework isn't "bound" to mapping a table to objects. Your data can come from multiple tables using different relations.
The same condition in the query is used in the update.
Question: does #addAll: work as a union?
a) No, but he does have , works as a union. - does a difference, etc.
students2 := students clone.
selfJoin := students * students2.
In SQL you need some way to differenciate the two different students in the join. #clone is used to get a distinct copy of the table. The alias knows the difference between the attributes of students and students2.
Really hairy SQL is produced, but the Smalltalk was much simpler than the SQL. And it worked.
result attributeGroupedByOriginalRelation
Doing this grouping shows that there are two sets of students relations. This is from the results set, we can break it up and tell where the information came from.
Question: So far its focused on the arbitrary queries. Have you done anything to marshall/unmarshall objects?
a) Effectively no. One thing he's played with is having a kind of wrapper. Decorate one of these relations in a mapping block that goes from tuple to object and object to tuple. When you iterate over that you get objects back instead. This doesn't exist yet though.
This system might make it much easier to make something like glorp.
ROE is plugged in to Seaside. It's a row relation so as you go from page to page it pulls from the database what it needs.
Lots of count(*) selects because something is sending #size much more than it should.
Question: Does he use transactions and rollbacks
a) No. The only system he knows of using this stuff commercially was a company using ROE and Seaside. They didn't need updates at first. They added connection pooling and transaction code on top of ROE. So there is code that does it but he hasn't gone through it or made it.
Results from selects are "raw" rows.
Question: Show us more about how you turn blocks in to tuples
a) RATuple knows what relation its in and knows what its attributes are. The tuple has a DNU. The DNU looks up attributes and returns that value. A RASelectTuple builds up a select tuple instead of running on results. Instead of returning an actual value for an attribute, it returns an RAAttributeNode. An RAConditionNode is the super class and understands all of the query methods, such as *, -, etc.
Question: Do you do type checking?
a) I don't do checking to see if a studentNumber is a 6. If you get something wrong you get a smalltalk error instead of a SQL error instead, which is much easier to debug.
students project: 'foo'
Got the error: #errorCouldNotResolveAttribute. It got that error before it even had to talk to the database.
Question: Do you use the parse tree of the block
a) I evaluate the block with the select tuple.
Question: Is ROE downloadable?
a) It's in SqueakMap and public store. Lots of unit tests.
Question: Is there any intention to build glorp on ROE?
a) No. One could do something glorp like, but glorp won't be.