postgresql-unit

repository·master·Indexed 43 days ago

https://github.com/df7cb/postgresql-unit

A PostgreSQL extension providing a robust datatype for SI units and other measurement systems. It supports complex unit arithmetic, automatic scale conversion, and thousands of units imported from GNU Units. Features include specialized conversion operators (@ and @@), custom prefix and unit definitions via unit_prefixes and unit_units tables, and support for shifted units like temperature.

Tokens
1.3K
Snippets
4
Records
6
Agent score
5%

What's inside postgresql-unit

  1. Perform unit arithmetic and conversions

    master

    The unit type supports standard arithmetic operators and specialized conversion operators.

    Arithmetic

    You can use +, -, *, /, and ^ to perform calculations between unit values. Multiplication binds tighter than division.

    Conversions

    • @ (unit @ text): Converts a unit to a new scale and returns the result as a unit type (including the unit label).
    • @@ (unit @@ text): Converts a unit to a new scale and returns the result as a double precision number.

    Note: The units on both sides must have the same dimension.

    -- Arithmetic
    SELECT '800 m'::unit + '500 m' AS length;
    SELECT '9.81 N'::unit / 'kg' AS gravity;
    
    -- Scale conversion (returns unit type)
    SELECT '2 MB/min'::unit @ 'GB/d' AS traffic;
    
    -- Scale conversion (returns double precision)
    SELECT '2 MB/min'::unit @@ 'GB/d';
  2. Understand shifted units (e.g., Temperature)

    master

    The extension handles units where zero is not absolute (like Celsius or Fahrenheit) using a shift value in the unit_units table.

    To avoid ambiguity, the shift is only applied in number name or plain name expressions (e.g., '5 °F'::unit). In all other contexts (like arithmetic or conversions), shifted units behave like base units without a shift. This ensures that a difference of 5 °C is treated as a 5-unit interval rather than an absolute temperature point.

    -- Absolute temperature (applies shift)
    SELECT '5 °F'::unit;
    
    -- Temperature interval (does NOT apply shift)
    SELECT '5 * °F'::unit;
    
    -- Conversion (applies shift)
    SELECT '5 °F'::unit @ '°C';
    
    -- Increment (does NOT apply shift)
    SELECT '5 °F'::unit @ '1 * °C' AS celsius_increments;
  3. Define custom prefixes and units

    master

    You can extend the library at runtime by inserting rows into the unit_prefixes and unit_units tables.

    Adding a Prefix

    Insert into unit_prefixes with a prefix and a factor.

    Adding a Unit

    Insert into unit_units with a name and a unit (which is a unit type value).

    Important: If you modify these tables, you must call unit_reset() to clear the backend-local cache, otherwise, your session will continue using the old definitions.

    -- Add a custom prefix
    INSERT INTO unit_prefixes VALUES ('foo', 42);
    
    -- Add a custom unit
    INSERT INTO unit_units VALUES ('legobrick', '9.6 mm');
    
    -- Clear cache to apply changes
    SELECT unit_reset();
  4. Install the unit extension

    master

    To use SI units in PostgreSQL, you must first install the unit extension. If compiling from source, you need PostgreSQL server headers, flex, and bison.

    On Debian-based systems, you can install dependencies and compile using:

    sudo apt-get install build-essential postgresql-server-dev-10 flex bison
    make PG_CONFIG=/usr/lib/postgresql/10/bin/pg_config
    sudo make install PG_CONFIG=/usr/lib/postgresql/10/bin/pg_config

    Once installed, enable it in your database with:

    CREATE EXTENSION unit;
    CREATE EXTENSION unit;
  5. Configure unit output formatting

    master

    You can control how unit values are displayed using the following GUC (Grand Unified Configuration) settings:

    • unit.byte_output_iec: Set to on to use IEC binary prefixes (Ki, Mi, Gi, etc.) for byte quantities. (Default: off)
    • unit.output_base_units: Set to on to format values using only base types without prefixes. (Default: off)
    • unit.output_superscript: Set to on to use Unicode superscripts for exponents. (Default: off)
    • unit.time_output_custom: Set to on to format time values $\ge$ 60s using minutes, hours, days, etc., instead of SI prefixes. (Default: on)

    Additionally, output precision is controlled by PostgreSQL's extra_float_digits. For 'nice' display of converted units in PostgreSQL 12+, you may need to set extra_float_digits = 0.

  6. Use the unit type API

    master

    The following functions are available for interacting with the unit type:

    FunctionSignatureDescription
    dimensionunit -> unitReturns the dimension of a unit (base units with normalized value of 1).
    valueunit -> double precisionReturns the numeric part of a unit value.
    roundunit -> unitRounds a unit value to the nearest integer in base units.
    unit_resetvoidClears the backend-local hash table used for unit lookups.
    unit_loadvoidReloads unit and prefix definitions from disk.
    unitrangeunit, unit or unit, unit, textCreates a range of units.

    Commonly used operators include +, -, *, /, ^, @, and @@.