Glorp and Schemas – a fix and a short login guide

I just fixed a bug in Glorp that prevents it from respecting the schema you set in the Login object.

Why do you need that?

In some shops, Schema names are used to distinguish certain project stages or “customer areas” from each other. So in one of my projects they’d have the same set of sql tables for each customer, each with their own schema name. E.g. they’d all have the same table named ADDRESS, but for each customer there would be a prefix like the customer id. All the tables are in the same DB2 instance, but can clearly be distinguished by prefixing the table name like this:

select * from CUSTNO43.ADDRESS where ...
insert into PREPROD.CUSTOMERS values ...

In Glorp, all the pieces for using a schema name with tables are there. They just don’t work. I know for sure about the current VA Smalltalk port, but skimming through the sources in VisualWorks I would guess this also doesn’t work there.

You can set a schema in a Login object, but it will never be used in Glorp.

I’ve submitted a bug fix to Instantiations to make sure they integrate it with Glorp and commit it back to Glorp base code (I don’t actually know where or how to commit to Glorp).

The change needed for schemas in Glorp is easy once you’ve found the place to add it to. If you need the change immediately and can’t wait for the actual change to make its way to your desk, here it is.  I just added the last line to DescriptorSystem>>#initializeTable:

initializeTable: newTable
 | initializerName |
 initializerName := ('tableFor' , (newTable name asUppercase) , ':') asSymbol.
 (self respondsTo: initializerName)
 ifTrue: [self perform: initializerName with: newTable]
 ifFalse: [self noTableInitializerFound: newTable].

 newTable postInitializeIn: self.

 self session ifNotNil: [:sess| newTable schema: sess schema].

For this to really work, you need to make sure that a new DB session is created in the right order. The easiest way to accomplish this is not to follow the usual documentation and set up a GlorpSession by sending the messages #system: and #accessor: to it by hand (because the order is important).

Instead you should use DescriptorSystem>>#sessionForlogin: which does all that’s needed.

Here is a full example of a Glorp login sequence:

myLogin := (Login new)
  username: 'testuser'; 
  password: 'mysecret';
  schema: 'CUSTNO43';
  database: DB2Platform new.
myAccessor := DatabaseAccessor forLogin: myLogin.
myAccessor login.
newSession := MyDescriptorSystem sessionForLogin: login.

newSession beginUnitOfWork.

I’m currently waiting for feedback from Instantiations and/or the core Glorp team whether the fix I sent in is okay to use. In my daily use it seems to be perfect, but Glorp is quite a complex piece of software and schemas are used in many places like naming indeces and constraints. So a little extra testing wouldn’t hurt.

Maybe somebody who reads this would be willing to try and give me feedback on whether they ancounter any problems with their preferred DBMS.