OK, it has been a while since the last time I published this data, but I have a valid excuse.
The most striking feature of the 2024 chart is the zero’ing out of IBM’s piece of the pie. Big Blue, which once billed the government $107M in a year, has been reduced to a billing rate of less than $5M per year over the last two years.
Everything else feels more or less the same. After seven years of NDP government, the overall trajectory of outsourcing growth has beeen flattened, but in no way reversed. It is a smaller proportion of overall spend, but the substantial change wrought by the Campbell Liberal government starting around 2005 has been durable – BC IT has a huge outsourced component still.
The initial surge in smaller local companies after 2017 stalled out by 2021 and had been flat since.
The most consistent grower is now CGI, which entered the Victoria market around 2005 and has grown to $60M/year in billings with consistent year-over-year increases.
I recently “celebrated” my “cancerversary”, the one-year mark since my GI doctor phoned me up and said the fateful words – “you have cancer”.
At that moment, my universe shrank down immensely. All the external stuff, job, professional relationships, volunteerism, just kind of fell away, I had no mental space for it. It was just me and my immediate family and the many, many unknowns.
My experience since then has included two major physical insults. The “curative” surgery that removed most of my rectum, and the associated c.difficle infection that brutally wrecked my GI tract.
The insults really knocked me back. Moving around the house involved effort. Meals would lead to stomach pain and long sessions on the toilet. Runs were replaced with walks and then shorter walks. A trip to the cafe became my gold standard for “getting out”.
Now, I am immensely “better” than I was this summer. But I am still a very long way from the physical condition I was before (which was excellent). My body just doesn’t work as well anymore. This may slowly resolve over more months, or it may be permanent. As it stands, I feel like I’ve been instantly aged 10-15 years. I went into this process in my 50s and came out in my 60s.
A result of feeling weak and out of control is that I have a lot less confidence than I used to. This manifests in not wanting to leave the house as much, or engage with novel situations. I never know when I am going to have a “bad day” and feel sick or uncomfortable for 24 hours. Travel feels fraught. Staying close to home, feels safer.
I am a turtle, startled and afraid, drawn up into its shell.
To try and break out of this pattern, I have scheduled two trips this spring, one personal and one professional. They are both east coast, so there’s a 5 hour flight involved and then all the usual transfers and so on. And then just “living” in a different place. As they get closer, I get more scared. I shouldn’t. The worst case scenario is just “pooping a lot in a hotel room”, but I think the verification of worse-case scenarios is the scary part – maybe I am not someone who travels anymore.
Most of my other pre-surgery worst-case scenarios have not come to pass. I am still able to climb. I have started running again. I can lift weights again. I have done some middling bike rides. I have rowed on the ocean. I have started some building projects around the house.
But travel is (like going out for dinner) fraught with being away from the home base, and full of questionable activities (like eating for pleasure, or taking a walk not knowing where the next public restroom is). Hopefully these trips will go well, and I will be able to poke my head a little further out of my shell.
The next station on my cancer journey will be the first monitoring procedures. Colonoscopy and then a CT scan. The odds of anything growing back are low, but I still keep my fingers crossed, since they are not zero.
A funny thing happened when I wrote up my 2025 book list – a lot of the books were parts of pairings. And I started wondering what other pairings I had read that were memorable.
You wouldn’t know it to look at me (or would you?) but I am a person who has read all 14 books of the original L. Frank Baum Oz series. From “The Wonderful Wizard of Oz” to “Glinda of Oz” and all in between.
As… that kind of person, I was truly tickled to pick up “Wicked” a couple years ago and take in not only the invented back-story of the Wicked Witch of the West (Elphaba), but also all the references to the Oz world that Maguire builds into his narrative. “Wicked” is the best kind of reimagining, one that manages a completely fresh story, but without tearing down the original source material on the way. Maguire clearly is also… that kind of person, and he treats Oz with respect while building a totally fresh take. Loved it so much.
I came across “Longbourne” as a book recommendation from the hosts of the Strict Scrutiny Podcast (a podcast that current events renders more relevant every day). Like “Wicked”, “Longbourne” picks in the same world as the source, but manages to tell an entirely unique story that pays tribute to the original.
“Longbourn” is told entirely from the point of view of the servants in the Bennet family home. It both tells a heart warming love story, and illuminates just how different the circumstances of the upstairs and downstairs of the house are.
The version I had conveniently included both “Longbourn” and the entirety of “Pride and Prejudice” in one volume. It was crazy to read the old novel and see just how little the service staff figured in the story. And yet, as “Longbourn” makes clear, they would have been omnipresent, working hard every day, 24/7.
“James” showed up on number of “best of” lists for 2024, and I deliberately read it after doing a re-read of Huck Finn. The central conceit of “James” is that the slaves are all play acting the character of “slave” in front of the white world, but have a rich secret intellectual life they only show to one another. This makes Everett’s “James” an engaging narrator, well read, ironic at times, and observant, but no more compelling as a human being than Twain’s “Jim”.
For me, after the first third of the book, “James” did not have a lot new to offer. Everett has to work through all the narrative beats of the original material, but does not have much more to offer than the central twist. In those parts of the story where James is separated from Huck, and Everett has the freedom to write his own narrative for James, I found the story more engaging, but when he is stuck inside Twain’s story arc, the book kind of grinds along.
“March” tells the tale of the largely absent father figure of “Little Women”, abolitionist Mr. March, who heads off join the Union Army as a chaplain, and ends up having as miserable a time as one would expect, in the Battle of the Wilderness and then on a Union-occupied plantation.
I found this book on the Pullitzer list (winner for 2006) and it was a great engaging read, good for anyone interested in a little Civil War fiction that does not shy away from just how miserable an experience war is. The human wreckage of battle, the devestation of every built structure, the disappearance of civil society and law. March heads off to war thinking he can make a difference. He returns much more realistic.
The “Demon Copperhead” and “David Copperfield” pairing I wrote about before. I picked up “Copperfield” right away after “Demon” to explore all the connections that Kingsolver had built into her tale, and I was a little surprised to find out how much she’d changed. Some of her characters had no analogues in Dickens and vice versa. Parts of the plot were gone or re-arranged or had no obvious analogue. Which was all fine, since “Demon Copperhead” stands perfectly well on its own.
Also wrote about these before. Worth reading together, if only to appreciate, in Newman’s telling, just how much of a self-absorbed prig Winston Smith actually is.
For PostGIS Day this year I researched a little into one of my favourite topics, the history of relational databases. I feel like in general we do not pay a lot of attention to history in software development. To quote Yoda, “All his life has he looked away… to the future, to the horizon. Never his mind on where he was. Hmm? What he was doing.”
Anyways, this year I took on the topic of the early history of spatial databases in particular. There was a lot going on in the ’90s in the field, and in many ways PostGIS was a late entrant, even though it gobbled up a lot of the user base eventually.
I have been watching the codification of spatial data types into GeoParquet and now GeoIceberg with some interest, since the work is near and dear to my heart.
Writing a disk serialization for PostGIS is basically an act of format standardization – albeit a standard with only one consumer – and many of the same issues that the Parquet and Iceberg implementations are thinking about are ones I dealt with too.
Here is an easy one: if you are going to use well-known binary for your serialiation (as GeoPackage, and GeoParquet do) you have to wrestle with the fact that the ISO/OGC standard for WKB does not describe a standard way to represent empty geometries.
Empty geometries come up frequently in the OGC/ISO standards, and they are simple to generate in real operations – just subtract a big thing from a small thing.
If you have a data set and are running operations on it, eventually you will generate some empties.
Which means your software needs to know how to store and transmit them.
Which means you need to know how to encode them in WKB.
And the standard is no help.
But I am!
WKB Commonalities
All WKB geometries start with 1-byte “byte order flag” followed by a 4-byte “geometry type”.
enum wkbByteOrder {
wkbXDR = 0, // Big Endian
wkbNDR = 1 // Little Endian
};
The byte order flag signals which “byte order” all the other numbers will be encoded with. Most modern hardware uses “least significant byte first” (aka “little endian”) ordering, so usually the value will be “1”, but readers must expect to occasionally get “big endian” encoded data.
The way to signal an empty collection is to set its numGeometries value to zero.
So for example, a MULTIPOLYGON EMPTY would look like this (all examples in little endian, spaces added between elements for legibility, using hex encoding).
01 06000000 00000000
The elements are:
The byte order flag
The geometry type (6 == MultiPolygon)
The number of sub-geometries (zero)
Polygons and LineStrings
The Polygon and LineString types are also very easy, because after their type number they both have a count of sub-objects (rings in the case of Polygon, points in the case of LineString) which can be set to zero to indicate an empty geometry.
For a LineString:
01 02000000 00000000
For a Polygon:
01 03000000 00000000
It is possible to create a Polygon made up of a non-zero number of empty linear rings. Is this construction empty? Probably. Should you make one of them? Probably not, since POLYGON EMPTY describes the case much more simply.
Points
Saving the best for last!
One of the strange blind spots of the ISO/OGC standards is the WKB Point. There is a standard text representation for an empty point, POINT EMPTY. But nowhere in the standard is there a description of a binary empty point, and the WKB structure of a point doesn’t really leave any place to hide one.
After the standard byte order flag and type number, the serialization goes directly into the coordinates. There’s no place to put in a zero.
In PostGIS we established our own add-on to the WKB standard, so we could successfully round-trip a POINT EMPTY through WKB – empty points are to be represented as a point with all coordinates set to the IEEE NaN value.
Here is a little-endian empty point.
01 01000000 000000000000F87F 000000000000F87F
And a big-endian one.
00 00000001 7FF8000000000000 7FF8000000000000
Most open source implementations of WKB have converged on this standardization of POINT EMPTY. The most common alternate behaviour is to convert POINT EMPTY object, which are not representable, into MULTIPOINT EMPTY objects, which are. This might be confusing (an empty point would round-trip back to something with a completely different type number).
In general, empty geometries create a lot of “angels dancing on the head of a pin” cases for functions that otherwise have very deterministic results.
“What is the distance in meters between a point and an empty polygon?” Zero? Infinity? NULL? NaN?
“What geometry type is the interesection of an empty polygon and empty line?” Do I care? I do if I am writing a database system and have to provide an answer.
The trouble with empty handling is that there are simultaneously a million different combinations of possibilities, and extremely low numbers of people actually exercising that code line. So it’s a massive time suck. We have basically been handling them on an “as needed” basis, as people open tickets on them.
Other Databases
SQL Server changes POINT EMPTY to MULTIPOINT EMPTY when generating WKB.