Updating multiple rows with SQL and avoiding collisions

I ran into an interesting problem with SQL the other day: how do you update multiple rows while maintaining an uniqueness constraint?

I have a table where each row describes an item in an ordered list. Each row has a position value. They are integers, not necessarily contiguous but each unique. A larger position means the row is further down the list. For reordering the rows, I sometimes need to make space between two positions.

How do you do that? Well, the obvious answer is a simple update statement, assuming you want to make space for one item before position 5:

UPDATE table
SET position = position + 1
WHERE position >= 5

Despite having used SQL since the 90s I don't think I've ever needed to do this before. It seemed simple enough, but I found out the solution I went with is not only obvious but also wrong. When you have contiguous position values, that statement causes a unique constraint violation, in both SQLite and PostgreSQL. Having transaction isolation doesn't prevent collisions during updates, even if the end state would be valid.

A helpful LLM tried to suggest the broken solution, then a solution that caused a syntax error and then a solution that involved creating a temporary table. After that I went back to searching the web and finally found a mention about negating the values temporarily which sounded like way less hassle than temporary tables.

That worked great. So, to add space for N items before position X:

  1. Begin transaction.
  2. Instead of incrementing the value on each row greater than or equal to X by N, multiply the value by -1 and decrement it by N.
  3. Multiply each value smaller than zero by -1.
  4. Commit.
BEGIN TRANSACTION;

UPDATE table
SET position = -position - 1
WHERE position >= 5;

UPDATE table
SET position = -position
WHERE position < 0;

COMMIT;

New Swift Package: tui-fuzzy-finder

Speaking of new Swift libraries, I released another one: tui-fuzzy-finder is a terminal UI library for Swift that provides an incremental search and selection UI that imitates the core functionality of fzf very closely.

I have a ton of scripts that wrap fzf. Some of them try to provide some kind of command line interface with options. Most of them work with pipes where I fetch data from somewhere, parse it with jq, feed it fzf, use the selection again as a part of a parameter for something else, etc. It's all great, except that I really don't love shell scripting.

With tui-fuzzy-finder I want to be able to write tools like that in a language I do actually enjoy a great deal. The package provides both a command line tool and a library, but the purpose of the command line tool is just to allow me to test the library, as writing automatic tests for terminal control is difficult. Competing with fzf in the general purpose CLI tool space is a non-goal.

I haven't implemented the preview features of fzf, nor key binding configuration. I'm not ruling either of those out, but I have not needed them yet and don't plan to work on them before a need arises.

Documentation at Swift Package Index.

New Swift Package: provision-info

I released a new Swift library! provision-info is a Swift package for macOS. Its purpose is to parse and show information about provisioning profile files. There's a command line tool and Swift library. The library part might work on iOS, too, but I have not tried. It relies on Apple's Security framework so no Linux.

It's not actually that new, but it's been sitting in a GitHub repo without any releases or changes for nearly three years. I needed the library in a tool at work a couple of weeks ago, so I added couple of features and finally made the first releases.

The CLI tool allows you to print out the basic metadata fields, the entitlements, the device IDs and the certificates in a profile file. You get them in plain text or as JSON. The library exposes the same data as Swift types.

There's documentation for the Swift APIs at Swift Package Index's excellent documentation hosting service. The command line tool prints out help with --help.

© Juri Pakaste 2025