The difference in ordering of enum type literals between PostgreSQL 9.0 and 9.1

≡放荡痞女 提交于 2020-01-24 09:29:46

问题


There has been some curious update in the way enum types work between PostgreSQL 9.0 and 9.1. The pg_catalog.pg_enum table has a new column enumsortorder in PostgreSQL 9.1. This order seems to override the previous enum ordering based on OIDs.

PostgreSQL 9.0 Documentation

The OIDs for a particular enum type are guaranteed to be ordered in the way the type should sort, but there is no guarantee about the ordering of OIDs of unrelated enum types.

PostgreSQL 9.1 Documentation

The OIDs for pg_enum rows follow a special rule: even-numbered OIDs are guaranteed to be ordered in the same way as the sort ordering of their enum type. That is, if two even OIDs belong to the same enum type, the smaller OID must have the smaller enumsortorder value. Odd-numbered OID values need bear no relationship to the sort order. This rule allows the enum comparison routines to avoid catalog lookups in many common cases. The routines that create and alter enum types attempt to assign even OIDs to enum values whenever possible.

When an enum type is created, its members are assigned sort-order positions 1..n. But members added later might be given negative or fractional values of enumsortorder. The only requirement on these values is that they be correctly ordered and unique within each enum type.

My question

For the jOOQ code generator, I'm reading the pg_catalog.pg_enum table, ordering enum literals by OID, the way it was specified in PostgreSQL 9.0. With the udpated specification, it seems that I should order the literals by enumsortorder, which seems to behave differently as it respects enum literal insertions "in the middle".

What's the most reliable, cross-version compatible way to read these enum literals from the pg_catalog?


回答1:


I think you'll need to check the PostgreSQL version and change behaviour appropriately, or use SQL that doesn't touch the catalog to determine the ordering.

An idea for the latter, given dummy enum:

CREATE TYPE test_enum AS ENUM ('z','x','y');
ALTER TYPE test_enum ADD VALUE 'a' BEFORE 'x';

is to ORDER BY the cast of the enum label to values of the enum type using the row_number window function available in 8.4 and newer:

SELECT enumlabel, row_number() OVER (ORDER BY enumlabel::test_enum) AS sort_key
FROM pg_catalog.pg_enum
WHERE enumtypid = 'test_enum'::regtype;

This gets you the labels ordered by a sort key. In older Pg versions Pg will just sort by the oid of the enum values, in newer versions it'll use the enumsortorder, but you don't have to care either way, you've just told PostgreSQL "sort these into the correct order please".

Or if you just need them in the order the server expects, write:

SELECT enumlabel
FROM pg_catalog.pg_enum
WHERE enumtypid = 'test_enum'::regtype
ORDER BY enumlabel::test_enum


来源:https://stackoverflow.com/questions/18398590/the-difference-in-ordering-of-enum-type-literals-between-postgresql-9-0-and-9-1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!