I've just published a VisualWorks port of version 3.8 of ROE to the Cincom public store. ROE is a Relational Object Expression system developed by Avi Bryant.
From the package comment "A library for manipulating relational queries
as first class Smalltalk expressions, and generating SQL from them. There's no documentation yet, but you can maybe muddle through using the test cases and some comments I made on my blog here: http://www.cincomsmalltalk.com/userblogs/avi/blogView?searchCategory=databas...."
In the latest version on Store, I've added support for the Oracle database. This required a bit of refactoring so I've branched on versions. I'll submit the changes to Avi to see if he wants integrate them into the main stream.
Brett Taylor
Hello, Brent and Avi
In the latest version on Store, I've added support for the Oracle database. This required a bit of refactoring so I've branched on versions. I'll submit the changes to Avi to see if he wants integrate them into the main stream.
Brett Taylor
I browsed your code in public store, and found your changes pretty suitable for me, so for me there is no much difference which one Avi will choose to include (if he wants). Basically there are next incompatibilities: 1){} brackets in tests (the single obvious solution) 2) symbols and string in tests (all reduced to strings) 3) RASqlPrinter & RASqlSingleTabler #printerOperator: monsters - the code is fine for squeak, but definitely not portable. My solution is: (for eliminating double code)
RANode>>sqlOperator
"other ways are: dynamic dictionary construction (as you did) and class var with dictionary." (operator = #&) ifTrue: [^' AND ']. (operator = #|) ifTrue: [^' OR ']. (operator = #~=) ifTrue: [^' != ']. (operator = #like) ifTrue: [^' LIKE ']. (operator = #ilike) ifTrue: [^' ILIKE ']. ^operator
and redefine: RASqlPrinter>>printOperator: aNode stream nextPutAll: aNode sqlOperator
RAPrinter>>printOperator: aNode stream nextPutAll: aNode operator
RASingleTableSqlPrinter>>printOperator: aNode stream nextPutAll: aNode sqlOperator (I'm probably again violating some conventions about what should be passed to what, but idea is clear)
4) unified resolution of strings and symbols. I forced it in: String>>resolveAttributeIn: aCollection ^ aCollection detect: [:ea | ea name asString = self] ifNone: [self errorCouldNotResolveAttribute] Symbol>>resolveAttributeIn: aCollection ^ aCollection detect: [:ea | ea name asSymbol = self] ifNone: [self errorCouldNotResolveAttribute]
RARelation>>attributeNamed: aString ifAbsent: errorBlock ...snipped... [:ea | ea name asString = aString asString ifTrue: ...snipped... 5) Finally, I'm created abstract RARealRelation for databases and pushed common functionality there. I also splitted #execute: into #exec: (no result queries) and #query: (queries returning values).
All this now can be filled in dolphin with some compatibility methods which are basically the same for dolphin and VW
Danil & Avi, I think it would be great to get rid of the Squeak specific code in the base as you have done. Did you implement support for other databases? In order to support Oracle, I factored out an Abstract class like your RARealRelation. I called it RADatabaseRelation. This allows the resolution of some problems - but I also found there were issues I couldn't resolve in this manner. 1) Different SQL Syntax: * Aliasing column names and table names is different between Oracle & Postgres * No support for the LIMIT operator in Oracle * Postgres EXCEPT operator is MINUS in Oracle 2) Attribute to Colummn name mapping fails in Oracle Oracle uses cases insensitive names by default. This causes #resolveAttributeIn: aCollection to fail and RARelation>>attributeNamed:ifAbsent: to fail.
I resolved these problems by adding a couple of classes. First of all - I created a class called the SqlDialect with subclasses OracleDialect & PostgresDialect. These classes handle dialect specific name resolution (through double dispatching) and determining which Printer class to use for generating SQL code. I also created a new SQL printer class RAOracleSqlPrinter which handles the differences in SQL code between the dialects.
There are other capabilities that are Database Driver specific such as the ability to use bind variables and bind arrays. Support for these can probably also be divided between the Relation, Dialect, and Printer. What do you think?
Brett Taylor On Tue, 2004-03-30 at 23:20, danil osipchuk wrote:
Hello, Brent and Avi
In the latest version on Store, I've added support for the Oracle database. This required a bit of refactoring so I've branched on versions. I'll submit the changes to Avi to see if he wants integrate them into the main stream.
Brett Taylor
I browsed your code in public store, and found your changes pretty suitable for me, so for me there is no much difference which one Avi will choose to include (if he wants). Basically there are next incompatibilities: 1){} brackets in tests (the single obvious solution) 2) symbols and string in tests (all reduced to strings) 3) RASqlPrinter & RASqlSingleTabler #printerOperator: monsters - the code is fine for squeak, but definitely not portable. My solution is: (for eliminating double code)
RANode>>sqlOperator
"other ways are: dynamic dictionary construction (as you did) and class var with dictionary."
(operator = #&) ifTrue: [^' AND ']. (operator = #|) ifTrue: [^' OR ']. (operator = #~=) ifTrue: [^' != ']. (operator = #like) ifTrue: [^' LIKE ']. (operator = #ilike) ifTrue: [^' ILIKE '].
^operator
Yeah - I wasn't so happy with my solution. The dictionary didn't buy anything.
and redefine: RASqlPrinter>>printOperator: aNode stream nextPutAll: aNode sqlOperator
RAPrinter>>printOperator: aNode stream nextPutAll: aNode operator
RASingleTableSqlPrinter>>printOperator: aNode stream nextPutAll: aNode sqlOperator (I'm probably again violating some conventions about what should be passed to what, but idea is clear)
- unified resolution of strings and symbols. I forced it in:
String>>resolveAttributeIn: aCollection ^ aCollection detect: [:ea | ea name asString = self] ifNone: [self errorCouldNotResolveAttribute] Symbol>>resolveAttributeIn: aCollection ^ aCollection detect: [:ea | ea name asSymbol = self] ifNone: [self errorCouldNotResolveAttribute]
RARelation>>attributeNamed: aString ifAbsent: errorBlock ...snipped... [:ea | ea name asString = aString asString ifTrue: ...snipped...
This looks good - but see above for my problem with case insensitive lookups.
- Finally, I'm created abstract RARealRelation for databases and pushed
common functionality there. I also splitted #execute: into #exec: (no result queries) and #query: (queries returning values).
This makes sense.
All this now can be filled in dolphin with some compatibility methods which are basically the same for dolphin and VW
Seaside mailing list Seaside@lists.squeakfoundation.org http://lists.squeakfoundation.org/listinfo/seaside
Brett Taylor wrote:
Danil & Avi, I think it would be great to get rid of the Squeak specific code in the base as you have done. Did you implement support for other databases? In order to support Oracle, I factored out an Abstract class like your RARealRelation. I called it RADatabaseRelation. This allows the resolution of some problems - but I also found there were issues I couldn't resolve in this manner.
- Different SQL Syntax: * Aliasing column names and table names is different between
Oracle & Postgres * No support for the LIMIT operator in Oracle * Postgres EXCEPT operator is MINUS in Oracle 2) Attribute to Colummn name mapping fails in Oracle Oracle uses cases insensitive names by default. This causes #resolveAttributeIn: aCollection to fail and RARelation>>attributeNamed:ifAbsent: to fail.
I resolved these problems by adding a couple of classes. First of all - I created a class called the SqlDialect with subclasses OracleDialect & PostgresDialect. These classes handle dialect specific name resolution (through double dispatching) and determining which Printer class to use for generating SQL code. I also created a new SQL printer class RAOracleSqlPrinter which handles the differences in SQL code between the dialects.
There are other capabilities that are Database Driver specific such as the ability to use bind variables and bind arrays. Support for these can probably also be divided between the Relation, Dialect, and Printer. What do you think?
This is cool Brett. Thanks. I may load this if I have playtime Friday and play with it. I wonder if its possible to do some sort of transform where we strip the RA prefixes and put the code in a first class VW namespace.
Travis, The code is in the Smalltalk.ROE namespace. Is this how you would do it? I originally did the class name transform manually. The code reads a little better in my opion. I hadn't automated it so I went back to the RA class name prefix to keep porting the code as simple as possible. I might try using the Refactoring Rewrite Tool to automate the translation of Class names (I always have to relearn how to use). I'll give it a try and publish it. Brett On Wed, 2004-03-31 at 09:18, Travis Griggs wrote:
Brett Taylor wrote:
Danil & Avi, I think it would be great to get rid of the Squeak specific code in the base as you have done. Did you implement support for other databases? In order to support Oracle, I factored out an Abstract class like your RARealRelation. I called it RADatabaseRelation. This allows the resolution of some problems - but I also found there were issues I couldn't resolve in this manner.
- Different SQL Syntax: * Aliasing column names and table names is different between
Oracle & Postgres * No support for the LIMIT operator in Oracle * Postgres EXCEPT operator is MINUS in Oracle 2) Attribute to Colummn name mapping fails in Oracle Oracle uses cases insensitive names by default. This causes #resolveAttributeIn: aCollection to fail and RARelation>>attributeNamed:ifAbsent: to fail.
I resolved these problems by adding a couple of classes. First of all - I created a class called the SqlDialect with subclasses OracleDialect & PostgresDialect. These classes handle dialect specific name resolution (through double dispatching) and determining which Printer class to use for generating SQL code. I also created a new SQL printer class RAOracleSqlPrinter which handles the differences in SQL code between the dialects.
There are other capabilities that are Database Driver specific such as the ability to use bind variables and bind arrays. Support for these can probably also be divided between the Relation, Dialect, and Printer. What do you think?
This is cool Brett. Thanks. I may load this if I have playtime Friday and play with it. I wonder if its possible to do some sort of transform where we strip the RA prefixes and put the code in a first class VW namespace.
On Mar 31, 2004, at 10:01 AM, Brett Taylor wrote:
Travis, The code is in the Smalltalk.ROE namespace. Is this how you would do it? I originally did the class name transform manually. The code reads a little better in my opion. I hadn't automated it so I went back to the RA class name prefix to keep porting the code as simple as possible. I might try using the Refactoring Rewrite Tool to automate the translation of Class names (I always have to relearn how to use). I'll give it a try and publish it.
One thing that might make an interesting CampSmalltalk project is developing a set of rewrite rules for porting code from Squeak to VW (and viceversa). Stripping/adding prefixes is an obvious one, but we might also be able to take care of {} and #caseOf:. You could also get rid of some support methods by doing some renames, ie, #signal <=> #raiseSignal.
Does anyone know how far Rosetta ST (http://rosettast.sourceforge.net/) goes in converting between Squeak and VW?
On Mar 31, 2004, at 11:01 AM, Avi Bryant wrote:
On Mar 31, 2004, at 10:01 AM, Brett Taylor wrote:
Travis, The code is in the Smalltalk.ROE namespace. Is this how you would do it? I originally did the class name transform manually. The code reads a little better in my opion. I hadn't automated it so I went back to the RA class name prefix to keep porting the code as simple as possible. I might try using the Refactoring Rewrite Tool to automate the translation of Class names (I always have to relearn how to use). I'll give it a try and publish it.
One thing that might make an interesting CampSmalltalk project is developing a set of rewrite rules for porting code from Squeak to VW (and viceversa). Stripping/adding prefixes is an obvious one, but we might also be able to take care of {} and #caseOf:. You could also get rid of some support methods by doing some renames, ie, #signal <=> #raiseSignal.
Seaside mailing list Seaside@lists.squeakfoundation.org http://lists.squeakfoundation.org/listinfo/seaside
---- Roger Whitney Department of Computer Science whitney@cs.sdsu.edu San Diego State University http://www.eli.sdsu.edu/ San Diego, CA 92182-7720 (619) 583-1978 (619) 594-3535 (office) (619) 594-6746 (fax)
Roger Whitney wrote:
Does anyone know how far Rosetta ST (http://rosettast.sourceforge.net/) goes in converting between Squeak and VW?
I bugged Joseph about this about 6 months ago, I was entertaining doing ROE/Seaside ports to VW and was balking at the prospect of always having to port/resolve the changes. Brett and David beat me to both ports :)
Joseph's report was not encouraging. Basically Rosetta can go to/from most of the Smalltalks, but not Squeak (maybe it can go one way to/from Squeak, but not both). His complaint was that Squeak had no canonized "package" or "application" concept. I know he had had thoughts long ago that Ginsu would provide that, but that fell by the wayside.
On Mar 31, 2004, at 11:07 PM, Travis Griggs wrote:
Roger Whitney wrote:
Does anyone know how far Rosetta ST (http://rosettast.sourceforge.net/) goes in converting between Squeak and VW?
I bugged Joseph about this about 6 months ago, I was entertaining doing ROE/Seaside ports to VW and was balking at the prospect of always having to port/resolve the changes. Brett and David beat me to both ports :)
Joseph's report was not encouraging. Basically Rosetta can go to/from most of the Smalltalks, but not Squeak (maybe it can go one way to/from Squeak, but not both). His complaint was that Squeak had no canonized "package" or "application" concept. I know he had had thoughts long ago that Ginsu would provide that, but that fell by the wayside.
Except that as I've told Joseph a few times, there *is* a standard package concept, it just doesn't happen to be Ginsu. Anyway, it would be really easy for me to output Rosetta format from Squeak if that were at all useful; I've just been outputting VW XML fileouts directly instead. Let me know what would be best.
Coolest IMO would be to get Monticello ported to Dolphin and VW so that we could all share a repository, but that's a lot of work...
Avi
Brett Taylor wrote:
Travis, The code is in the Smalltalk.ROE namespace. Is this how you would do it? I originally did the class name transform manually. The code reads a little better in my opion. I hadn't automated it so I went back to the RA class name prefix to keep porting the code as simple as possible. I might try using the Refactoring Rewrite Tool to automate the translation of Class names (I always have to relearn how to use). I'll give it a try and publish it.
That is exactly how I would do it. I got so excited I had to go and load it (instead of waiting til Friday). My response could be longish, I'll use headers to break it up. :)
PACKAGING CHANGES
I made a change; a change that you're free to say "no Travis, I did it first, do it my way". I loathe Bundles for a litany of reasons (I don't mind categories), I even know that my loathing seems to be somewhat of minority, so don't take it personally. :) Anyway, I "refactored" the packages into three Packages:
+ ROE-SqueakCompatibility - similiar to the one you had, but restricted as best as I could to class extensions which would be found in a Squeak image regardless of ROE being loaded or not + ROE - mostly everything else, I left all of the categories in place + ROE-SUnitTests - all of the Tests, pretty much the same thing as yours but I didn't want to overwrite your work, so I used a different name
Packaged such, I could entertain the NewPrerequisiteEngine to compute prereqs for them and did so, they each have fully fleshed prereqs. Anyway, like I say, you can ignore my repackaging entirely, look at them and tell me no way, etc. I did it as a demonstration of doing it without bundles.
CLASS RENAMING
I figured out a general workspace snippet to rename all of the classes. It looks something like:
Roe classes do: [:each | ('RA*' match: each name) ifTrue: [| refactoring | Transcript show: each name; cr. refactoring := (RenameObjectRefactoring renameObjectNamed: each fullName to: (each name copyFrom: 3 to: each name size)). refactoring transform. RefactoringManager instance addRefactoring: refactoring]]
The "Transcript show:" is in there, because it takes a bit of time to crunch through it all and it gives you a sanity check that it is making progress. What it does not do for you is provide back pointer aliases so that new fileins from Squeak would be able to find the newly named class and add/remove/modify code to it. One way to do this *might* be to have a separate package which provided class aliases in the Smalltalk namespace. For example, when renaming ROE.RABinaryNode to ROE.BinaryNode, it also does a (Smalltalk at: #RABinaryNode put: ROE.BinaryNode). It's a thought.
Also, is there a better name for RAPrinter than Printer? It's just a SerializationVisitor, right?
CIRCULAR PREREQUISITES
One of the things I noticed with the package refactoring, is that ROE wanted to depend on ROE-SUnitTests (which in turn of course depends on it). This seemed to be caught up in MappedCollection. I didn't spend too much time chasing it (got to get home and go to bed so I can go spring skiing tomorrow).
CODE CRITIC
Having it in VW with the RB, gave me the chance to throw the Code Critic at the ROE package. I took a snapshot of the top level report window and attached it as a .png for any that are interested.
TESTS
Most of the tests passed. Except TestSemantics. All of those failed. It looks like maybe this is an abstract test class...? And TestSyntax>>testErrors failed as well. Other than that, lots of green test tubes. :)
On Mar 31, 2004, at 11:19 PM, Travis Griggs wrote:
Also, is there a better name for RAPrinter than Printer? It's just a SerializationVisitor, right?
Yes. Not sure I like that name any better, though.
One of the things I noticed with the package refactoring, is that ROE wanted to depend on ROE-SUnitTests (which in turn of course depends on it). This seemed to be caught up in MappedCollection. I didn't spend too much time chasing it (got to get home and go to bed so I can go spring skiing tomorrow).
Odd. Let me know if you figure out why.
Most of the tests passed. Except TestSemantics. All of those failed. It looks like maybe this is an abstract test class...?
Yup.
On Mar 31, 2004, at 8:48 AM, Brett Taylor wrote:
I resolved these problems by adding a couple of classes. First of all
I created a class called the SqlDialect with subclasses OracleDialect & PostgresDialect. These classes handle dialect specific name resolution (through double dispatching) and determining which Printer class to use for generating SQL code. I also created a new SQL printer class RAOracleSqlPrinter which handles the differences in SQL code between the dialects.
I'll look at your code, but it sounds reasonable. I've known I would have to at least have multiple SqlPrinter classes. This may make more sense when I actually look at it, but my initial response is to wonder why you need three classes (Relation, Dialect, Printer) for each - wouldn't just Relation and Printer be enough, with some methods on Relation like #printerClass that got overridden?
Avi
On Wed, 2004-03-31 at 10:58, Avi Bryant wrote:
On Mar 31, 2004, at 8:48 AM, Brett Taylor wrote:
I resolved these problems by adding a couple of classes. First of all
I created a class called the SqlDialect with subclasses OracleDialect & PostgresDialect. These classes handle dialect specific name resolution (through double dispatching) and determining which Printer class to use for generating SQL code. I also created a new SQL printer class RAOracleSqlPrinter which handles the differences in SQL code between the dialects.
I'll look at your code, but it sounds reasonable. I've known I would have to at least have multiple SqlPrinter classes. This may make more sense when I actually look at it, but my initial response is to wonder why you need three classes (Relation, Dialect, Printer) for each - wouldn't just Relation and Printer be enough, with some methods on Relation like #printerClass that got overridden?
Well - it seemed reasonable to add the Dialect specific classes at the time, but you are right, there was no need for them at this point. I refactored the code to use the concreteRelation for all of this behavior. All of the test cases run as before. I've published this to the public store. Brett
Avi
Seaside mailing list Seaside@lists.squeakfoundation.org http://lists.squeakfoundation.org/listinfo/seaside
Brett, Dolphin talks to db via ODBC, so I adapted ROE to it's db connectivity code and checked it with PostrgesSQL (I want to try firebird, but didn't yet). As roe is now exposed to much more skillful audience I'll be a spectator further (and I'm sure that all will be allright:)) P.S. My apologies for misspelling your name in previuos message (and for my poor English in general :)
Danil & Avi, I think it would be great to get rid of the Squeak specific code in the base as you have done. Did you implement support for other databases? In order to support Oracle, I factored out an Abstract class like your RARealRelation. I called it RADatabaseRelation. This allows the resolution of some problems - but I also found there were issues I couldn't resolve in this manner.
- Different SQL Syntax:
- Aliasing column names and table names is different between Oracle &
Postgres
- No support for the LIMIT operator in Oracle
- Postgres EXCEPT operator is MINUS in Oracle
- Attribute to Colummn name mapping fails in Oracle
Oracle uses cases insensitive names by default. This causes #resolveAttributeIn: aCollection to fail and RARelation>>attributeNamed:ifAbsent: to fail.
I resolved these problems by adding a couple of classes. First of all - I created a class called the SqlDialect with subclasses OracleDialect & PostgresDialect. These classes handle dialect specific name resolution (through double dispatching) and determining which Printer class to use for generating SQL code. I also created a new SQL printer class RAOracleSqlPrinter which handles the differences in SQL code between the dialects.
There are other capabilities that are Database Driver specific such as the ability to use bind variables and bind arrays. Support for these can probably also be divided between the Relation, Dialect, and Printer. What do you think?
Brett Taylor On Tue, 2004-03-30 at 23:20, danil osipchuk wrote:
seaside@lists.squeakfoundation.org