Thursday, April 21, 2005

O-verkill-racle

Oracle's had a philosophy for a while now that, "We're the database company; so anytime our software has to interact with any data, for any reason, we'll have it create an Oracle database for the purpose."

The trouble is, an Oracle database represents a LOT of overhead. For instance, an empty Oracle database takes ten times the disk space of an empty postgresql database. Worse, every new database is a new administration burden.

We wanted to do a little bit - a very little bit - with web-based Oracle Discoverer. That meant installing Oracle Application Server, and OAS created its very own infrastructure database. Now I've got this "infrastructure" database sitting around, doing next to nothing, soaking up almost as much disk space and memory as a small production database would. It's 9.0.1 - way behind my own databases - and I have to attend to its obsolete 9.0.1 security needs, or the network security scan gripes at me.

And the shame of it is - a use like this doesn't need the things an RDBMS provides. A store of configuration data for an application server doesn't need multi-user access, transactional consistency, etc. etc. - totally unnecessary. A few flat files would do fine.

It's like a trucking company that won't use a hand dolly because, well, they're a trucking company. So, of course, they need diesel pumps and regular oil changes and overhauls for the big rigs they use to get the copy paper down to the copy room, and maneuvering the 18-wheelers between the cubicles may be a little troublesome sometimes.

passwords in LSNRCTL

Oracle's listener control (LSNRCTL) can take a password. The way you actually supply the password is very confusing, though.

c: > lsnrctl
LSNRCTL> stop
TNS-01169: The listener has not recognized the password


What do you mean, "Did not recognize the password?" You never asked for a password!

LSNRCTL> set password badguess
LSNRCTL > stop

TNS-01169: The listener has not recognized the password
LSNRCTL> set password goodguess

LSNRCTL > stop
The command completed successfully


In other words... 'set password' doesn't mean 'set password' the way normal human beings mean it - 'establish this as the password'. It means, 'this is what I think the password is, so transmit this whenever I do something that demands a password'.

Humph. There should be a category for "not exactly a bug, but nomenclature confusing enough that it may as well be".

Monday, April 11, 2005

For the first time in my life, I find myself worried about mutability.

I want to take advantage of Python's new sets (who wouldn't?). It turns out that sets can only be made of immutable, hashable objects, and a user-created object type is (by definition) mutable.

I can see where it makes sense. If I say
box1 = Box(contents='eggs')
box2 = Box(contents='eggs')
basket = set([box1, box2])
should basket contain one or two items?
Now suppose I
box2.contents = 'yogurt'
Now does my basket have a box of eggs and a box of yogurt, or just one box of yogurt? It's not clear.

The problem is, there are objects I will create that truly never will change, and it truly would be useful to use this wonderful set functionality with them. So now I'd like to be able to create immutable objects, but Python has no particular way to create them.

The only way I've found so far feels a little bit dangerous - to define __hash__. As far as I can tell, it means "You can know me by this". If I do forget and later change data that is the basis of my hash, my object no longer hashes to what it once did - it has moved and left no forwarding address. There are some clumsy ways to try to block later changes to my object's values, but they are... clumsy. (Redefining the object's __setattr__ and raising exceptions therein. Ick.)

Thus, it feels like I'm delving into eldritch secrets, like my soul is toast if I scuff the pentagram. __str__ and __cmp__ are the only double-underscore methods I'd defined previously. They feel downright warm and fuzzy compared to this.