Category: General

  • SQLEditor 2.5 – now with native database drivers and process separation

    I’m really happy to say that SQLEditor 2.5 [60MB zip]  has just been released. This has some interesting new features that have been in development for some time. Native database drivers have been something I’ve been hoping to support for ages, while process separation should improve stability and performance.

    Native database drivers

    SQLEditor 2.5 now includes native database support bundled with the app.
    Native drivers are bundled for SQLite (using standard sqlite), MySQL/Drizzle (using the Drizzle driver library) and Postgres (using Postgres client libraries).

    The native drivers don’t use Java at all, which gives a marginal performance improvement. Although if you’re using SQLEditor in standard, graphical mode you probably won’t notice.

    Native driver support means that SQLEditor should now be zero configuration for many users. Just install the app and start using it. This should be a big win, as opposed to finding, downloading and installing the JDBC drivers. It also gives a predictable and standard configuration to test, which should reduce bugs.

    SQLEditor still supports JDBC drivers as before, but if you definitely don’t require them, the JDBC driver loading can be turned off entirely.
    (Preferences->Database->Database Options->Enable Java (JDBC) Driver Support)

    Database process separation

    SQLEditor 2.5 now splits off database operations and anything involving Java into a separate process. This was primarily to provide more protection with native drivers, if they crash. However it also means that there is no Java VM running in the main process at all, which should make SQLEditor open an editable document faster from cold start. The worker thread is started, but can then load java separately, you don’t need to wait for this to happen.There is also better stability should JDBC driver discovery hang or crash, because this is running in a third process.

    Overall there are more processes, but it doesn’t seem to make that much difference memory wise. Plus Chrome does something similar, so SQLEditor is in good company (or so I’m hoping).

    The new version is available to download today:

    SQLEditor 2.5 [60MB zip, 10.6+]

    Alternatively the in-app updater should be offering the upgrade right now.

    Upgrading via the in-app updater also reduces the download size, because, in many cases, it only downloads the changes between versions, rather than the whole app.
    (thanks Sparkle)

    I hope that you like the new release, if you have comments or wish to report a bug please do email at support@malcolmhardie.com 

  • Corporation must maximise profits (?)

    I’ve had this post sitting in my drafts collection for ages, but after reading yet another person make this claim about corporations, I’ve decided to post it. I believe that my sources are correct and accurate, note that the main source now links to the internet archive, rather than the original paper, because the congressional committee site has been rearranged. Please comment or email if you have any questions or concerns.


    This is something that pops up fairly frequently, the idea that corporations are required as their sole duty to maximise profits to shareholders.

    While a handy tool to create a nice documentary, this statement has been described [pdf] by Professor Margaret Blair of Vanderbilt University Law School as

    “… [A]t best, a misleading overstatement”. “At worst, this claim is simply false”… “There is no statutory requirement in the U.S. that corporations must maximize profits, or that directors are responsible for maximizing share value.”

    “Case law ” … “also does not require share value maximization, except in one very narrow circumstance: When, in the course of buyout negotiations it becomes inevitable that a corporation will be sold” … “directors’ duties then change” … “to auctioneers charged with getting the best price for stockholders at a sale of the company”

    And in other places like the UK?

    “In Britain, for example, the British Companies Act 2006 explicitly codified what lawmakers believed to be the rule under their case law, which provides that directors have duties to multiple stakeholders”

    So what makes directors focus on profit maximisation? Prof. Blair offers the following:

    “… pressure comes from the media, from shareholder advocates and financial institutions in whose direct interest it is for the company to get its share price to go up, and from the self-imposed pressure created by compensation packages that provide enormous potential rewards for directors and managers if stock prices go up.”

    NOTE: The above has been slightly edited for length. Hopefully without affecting original meaning and intention.

    (Original Testimony to US House Of Representatives Committee [PDF])

    Originally I found much of this from [Economic Populist: Corporate Citizen – An Oxymoron”]

    This doesn’t in any sense excuse companies that behave badly. In fact it adds criticism to them; if they are NOT legally required to behave badly, why do they still continue to do so?

  • Exporting SVG from Cocoa

    Following from my previous post about SVG exporting in cocoa, here are some details on how this is done in SQLEditor. The example code is extracted from the live SQLEditor code base, but it’s been altered to simplify in a few places. Hopefully it doesn’t contain any bugs, but please point them out if you see them.

    In addition, I don’t offer this up particularly as a tutorial, this is just the way that I did it, so there are possibly (probably?) better ways of doing this. Feel free to reuse any of it, in any way, if you wish using either BSD or Attribution 3.0 Unported . I’ll try and put a complete working example of it up on github soon. Update: Source code now on github

    The key point is that SVG is just a dialect of XML. This means that we can use NSXMLDocument and friends to generate the SVG, which makes life much easier than it would be otherwise.

    We use a standard NSXMLDocument

    - (NSXMLDocument*)xmlDocument
    {
    id rootNode = [self exportToXMLNode];
    id xmlDocument = [[[NSXMLDocument alloc] initWithRootElement:rootNode] autorelease];
    [xmlDocument setVersion:@"1.0"];
    [xmlDocument setCharacterEncoding:@"UTF-8"];
    return xmlDocument;
    }

    The code to generate the root node looks like this:

    - (NSXMLNode*)exportToXMLNode
    {
        id exportNode = [NSXMLElement elementWithName:@"svg"];
    
    	id viewBoxString = [NSString stringWithFormat:@"%.0f %.0f %.0f %.0f",imageBounds.origin.x,imageBounds.origin.y,imageBounds.size.width,imageBounds.size.height];
    
        [exportNode addAttribute:[NSXMLNode attributeWithName:@"viewBox" stringValue:viewBoxString]];
        [exportNode addAttribute:[NSXMLNode attributeWithName:@"width"
                                                  stringValue:[NSString stringWithFormat:@"%.0f",imageBounds.size.width]]];
        [exportNode addAttribute:[NSXMLNode attributeWithName:@"height"
                                                  stringValue:[NSString stringWithFormat:@"%.0f",imageBounds.size.height]]];
    
        id namespace = [NSXMLNode namespaceWithName:@"" stringValue:@"http://www.w3.org/2000/svg"];
        [exportNode setNamespaces:[NSArray arrayWithObject:namespace]];
    
        id transformGroup = [NSXMLNode elementWithName:@"g"];
        [transformGroup addAttribute:[NSXMLNode attributeWithName:@"transform" stringValue:@"translate(0.5,0.5)"]];
    
        [exportNode addChild:transformGroup];
    
        for (id entry in [self.container objectListByZOrder]) {
    
            if (![entry getPropertyAsBoolean:@"hidden"]) {
                    id newNode = [self exportObjectToSVG:entry];
    
                    if (newNode) {
                        [transformGroup addChild:newNode];
                    }
                }
    
        }
    
    	return exportNode;
    }

    objectListByZOrder returns an array of objects, ordered by zOrder, from back to front.

    We use a transform group with an offset of (0.5,0.5) to align the image to the screen pixels. (The alternative would be to draw everything at 0.5 pixel offsets, but this is annoying)

    We also use a viewBox, which is set to the value of imageBounds, a variable which contains the bounding rectangle of the objects in the document. This is already set up by the time this code is called.

    getPropertyAsBoolean is part of the SQLEditor object properties system and in this case, its used to determine whether the object being drawn is hidden or not. Obviously if it’s hidden, then it doesn’t get drawn. At least one beta version of SQLEditor overlooked this fairly obvious point.  🙂

    Now finally, an example object exporting section:

    - (id)textElement:(NSString *)text atPoint:(NSPoint)textLocation
    {
        id titleText = [MHSVGElement elementWithName:@"text"];
        id titleAttributes = [NSMutableDictionary dictionaryWithCapacity:1];
        [titleAttributes addEntriesFromDictionary:[self dictionaryForLocation:textLocation]];
        [titleAttributes setObject:@"10" forKey:@"dx"];
        [titleAttributes setObject:@"14" forKey:@"dy"];
        [titleAttributes setObject:@"black" forKey:@"fill"];
        [titleAttributes setObject:@"13" forKey:@"font-size"];
        [titleAttributes setObject:@"Lucida Grande" forKey:@"font-family"];
        [titleAttributes setObject:@"optimizeLegibility" forKey:@"text-rendering"];
    
        [titleText setAttributesWithDictionary:titleAttributes];
    
        [titleText setStringValue:text];
        return titleText;
    }
    
    - (id)rectangleElement:(NSRect)objectRect
                 fillColor:(NSColor*)color
               strokeColor:(NSColor*)strokeColor
              cornerRadius:(NSUInteger)radius
    {
        id mainFrame = [MHSVGElement elementWithName:@"rect"];
    
        id attributes = [NSMutableDictionary dictionaryWithCapacity:1];
    
        [attributes addEntriesFromDictionary:[self dictionaryForLocation:objectRect.origin]];
        [attributes addEntriesFromDictionary:[self dictionaryForSize:objectRect.size]];
        [attributes setObject:[NSNumber numberWithInteger:radius] forKey:@"rx"];
        [attributes setObject:[NSNumber numberWithInteger:radius] forKey:@"ry"];
    
        id strokeColorString = @"none";
    
        if (strokeColor) {
            strokeColorString = [self svgColor:strokeColor];
            [attributes setObject:@"1" forKey:@"stroke-width"];
            [attributes setObject:strokeColorString forKey:@"stroke"];
        }
    
        NSString* fillColorString = [self svgColor:color];
    
        [attributes setObject:fillColorString forKey:@"fill"];
        [attributes setObject:[NSString stringWithFormat:@"%f",[color alphaComponent]] forKey:@"fill-opacity"];
    
        [mainFrame setAttributesWithDictionary:attributes];
    
        return mainFrame;
    }
    
    - (NSXMLNode*)exportSQLCanvasAreaToSVG:(SQLCanvasArea*)object
    {
    
        id commentGroup = [MHSVGElement elementWithName:@"g"];
    
        [commentGroup addAttribute:[NSXMLNode attributeWithName:@"class" stringValue:@"SQLCanvasArea"]];
    
        NSRect areaRect;
        areaRect.origin = [object location];
        areaRect.size = [object size];
    
        id mainFrame = [self rectangleElement:areaRect
                                    fillColor:[self labelColorForObject:object]
                                  strokeColor:[NSColor blackColor]
                                 cornerRadius:5];
    
        [commentGroup addChild:mainFrame];
    
        id titleText = [self textElement:[object getName] atPoint:[object location]];
        [titleText addAttribute:[NSXMLElement attributeWithName:@"font-family" stringValue:@"Lucida Grande"]];
        [titleText addAttribute:[NSXMLElement attributeWithName:@"font-weight" stringValue:@"bold"]];
    
        [commentGroup addChild:titleText];
    
        return commentGroup;
    }

    Each object has a specific export<objectClass>ToSVG method, in this caseexportSQLCanvasAreaToSVG. It sets up a new group, draws the background and the title, then returns the xml element back, so it can be added to the main image.

    At minimum, splitting up the drawing by object type is a good idea, probably better to have separate classes for drawing each type (possibly with some inheritance or composition)

    As you can see, the text drawing section makes a number of hard coded assumptions right now. Those were chosen to match the SQLEditor default drawing styles as closely as possible. It’s not a perfect match though, due to the variation between drawing in a cocoa NSView/NSWindow vs drawing in a SVG context (usually in a browser). Fonts are something of an issue and there are issues with rendering across platforms.

    Overall though, I’m quite pleased, the first phase of SVG export didn’t prove too troublesome to implement and added a useful feature to SQLEditor without either too much coding, or any extra dependencies.

    Update
    Example code (with minor changes) now on github: https://github.com/AngusHardie/cocoasvgexperiment

  • A memorial to lab mice

    Statue of a mouse knitting dna (imgur)- apparently a memorial to laboratory mice.

    Regardless of opinions about lab use of animals, I think a statue remembering them is correct and proper.

  • New SQLEditor database connection panel

    The database connection setup panel in SQLEditor has been something I’ve been hoping to improve for a while.

    This is the first attempt at a redesign:

    sqleditor-new-db

     

    The connections are now listed in a collapsable sidebar and can be both added and removed. You can also edit the connection in the main area. Changes are automatically saved.

    It’s not ready yet, but it may appear sometime soon.

  • Xbox 360 and Playstation 3 were released before first iPhone

    Xbox 360 released November 16, 2005 in USA
    Playstation 3 released November 11, 2006, in Japan
    Original iPhone released June 29, 2007, in USA - superseded 5 times

    The consoles are still competitive platforms. Nothing in the phone world lasts that well.

    This is not a criticism of the iPhone, which is a brilliant device, instead a thought about the longevity of the consoles.

  • Is “Maximising Shareholder value” required – no it’s not

    http://www.guardian.co.uk/sustainable-business/blog/maximising-shareholder-value-irony

    The idea only dates from about 1976, it doesn’t seem to be in any law and it probably doesn’t lead to the best outcomes anyway.

  • Multi-touch – finger tips wearing out?

    I seem to be using more multi-touch stuff, but I do have this irrational fear that my finger tips will slowly start to wear away from constantly dragging them over metal or glass surfaces …

     

  • Russian Documentary about Bread Day

    Years ago I saw a documentary about Russians living in the country side where the local people had to push, by hand, a railway wagon filled with bread.

    I could never find any trace of it later, but today I did:

    Chlebnyy den (Bread Day) 1998
    Directed by Sergei Dvortsevoy

    The Harvard Film Archive showed it a while ago

  • More modifier keys

    I was working on the new labels panel in SQLEditor when I realised that I’d run out of modifier keys for clicking shortcuts. Tables already use several of the standard keys for selection control, leaving pretty much only option/alt remaining, and I’d already used it for something else. 🙁

    Apple: please provide more modifier keys on the keyboard for even more complicated shortcuts!

    😉

    (Or more rationally, I’ll probably change it around and the commands will end up in a popup menu or something, which is actually better for discoverability anyway)