Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
66ea093
initial prototype
dantownsend Oct 22, 2025
f92d1eb
fix docstring
dantownsend Oct 22, 2025
94a0482
fix test
dantownsend Oct 22, 2025
1e7191b
simplify backport
dantownsend Oct 22, 2025
981cb5a
add basic test
dantownsend Oct 22, 2025
5943774
don't run test for cockroachdb
dantownsend Oct 25, 2025
4740f3e
Merge branch 'master' into pr/1284
dantownsend Nov 15, 2025
0c784c7
Merge branch 'master' into pr/1284
dantownsend Nov 15, 2025
2da5ff2
add `UUID7` to api reference
dantownsend Nov 15, 2025
8845550
Merge branch 'master' into pr/1284
dantownsend Jan 12, 2026
7983279
Merge branch 'master' into pr/1284
dantownsend Feb 12, 2026
33d4c9c
load script for older versions of Postgres / CockroachDB
dantownsend Feb 12, 2026
faa46ce
add tutorial
dantownsend Feb 12, 2026
63945cd
Update uuid_v7_support.rst
dantownsend Feb 12, 2026
06afb29
add polyfills
dantownsend Feb 12, 2026
04493d5
try fixing cockroachdb test
dantownsend Feb 12, 2026
bcab76f
disable uuid7 for cockroachdb for now
dantownsend Feb 12, 2026
ce96f7b
update docs
dantownsend Feb 12, 2026
0f00b16
Merge branch 'master' into 1280-uuidv7
dantownsend Feb 26, 2026
871a013
Merge branch 'master' into 1280-uuidv7
dantownsend Feb 27, 2026
39ff533
just support python 3.14
dantownsend Feb 27, 2026
d6292de
tweaks
dantownsend Feb 27, 2026
1b6245c
fix linter error
dantownsend Feb 27, 2026
8fcbba6
add docstring
dantownsend Feb 27, 2026
eb7d493
update `python_version_gte`
dantownsend Feb 27, 2026
a8423b3
Update test_uuid.py
dantownsend Feb 27, 2026
73aa7c2
make defaults None so it is possible to use on cockroach and sqlite -…
dantownsend Mar 6, 2026
323aa12
Merge branch 'master' into pr/1364
dantownsend Mar 6, 2026
1cff969
mention extension for older pg versions
dantownsend Mar 6, 2026
d1ebf6d
Merge branch 'master' into pr/1364
dantownsend Mar 6, 2026
a88b3f9
Update index.rst
dantownsend Mar 6, 2026
e956738
fix `python_version_gte`
dantownsend Mar 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 6 additions & 17 deletions docs/src/piccolo/api_reference/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -111,42 +111,31 @@ UUID
~~~~

.. autoclass:: UUID4
:members:

.. autoclass:: UUID7


TimestampCustom
~~~~~~~~~~~~~~~
Timestamp
~~~~~~~~~

.. autoclass:: TimestampCustom
:members:

TimestampOffset
~~~~~~~~~~~~~~~

.. autoclass:: TimestampOffset
:members:

TimestampNow
~~~~~~~~~~~~

.. autoclass:: TimestampNow
:members:

TimestamptzCustom
~~~~~~~~~~~~~~~~~
Timestamptz
~~~~~~~~~~~

.. autoclass:: TimestamptzCustom
:members:

TimestamptzOffset
~~~~~~~~~~~~~~~~~

.. autoclass:: TimestamptzOffset
:members:

TimestamptzNow
~~~~~~~~~~~~~~

.. autoclass:: TimestamptzNow
:members:

Expand Down
4 changes: 2 additions & 2 deletions docs/src/piccolo/contributing/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ Make sure the test database exists:
.. code-block:: console

cockroach sql --insecure
>>> create database piccolo
>>> use piccolo
>>> create database piccolo;
>>> use piccolo;

-------------------------------------------------------------------------------

Expand Down
62 changes: 59 additions & 3 deletions piccolo/columns/defaults/uuid.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from enum import Enum
from typing import Union

from piccolo.utils.uuid import uuid7

from .base import Default


Expand All @@ -17,6 +19,18 @@ class UUID4(Default):

@property
def postgres(self):
"""
Historically we had to use `uuid_generate_v4()` from the `uuid-ossp`
extension.

Since Postgres 13 there is a built-in `gen_random_uuid` function which
generates UUID v4 values.

In Postgres 18, `uuidv4` was added, which is the same as
`gen_random_uuid`, but more precisely named. We will move to this at
some point in the future.

"""
return "gen_random_uuid()"

@property
Expand All @@ -25,13 +39,55 @@ def cockroach(self):

@property
def sqlite(self):
return "''"
return None

def python(self):
return uuid.uuid4()


UUIDArg = Union[UUID4, uuid.UUID, str, Enum, None, Callable[[], uuid.UUID]]
class UUID7(Default):
"""
This makes the default value for a
:class:`UUID <piccolo.columns.column_types.UUID>` column a randomly
generated UUID v7 value. Postgres >= 18 and Python >= 3.14 only. UUID7 can
be more efficiently indexed than UUID, and inserts can be faster.

For this to work in older versions of Postgres, register an extension such
as `pg_uuidv7 <https://github.com/fboulnois/pg_uuidv7>`_.

""" # noqa: E501

@property
def postgres(self):
"""
Supported in Postgres 18 and above.
"""
return "uuidv7()"

@property
def cockroach(self):
"""
CockroachDB doesn't currently have a uuidv7 function.
"""
return None

@property
def sqlite(self):
return None

def python(self):
return uuid7()


UUIDArg = Union[
UUID4,
UUID7,
uuid.UUID,
str,
Enum,
None,
Callable[[], uuid.UUID],
]


__all__ = ["UUIDArg", "UUID4"]
__all__ = ["UUIDArg", "UUID4", "UUID7"]
4 changes: 4 additions & 0 deletions piccolo/utils/uuid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
def uuid7():
from uuid import uuid7 as _uuid7

return _uuid7()
12 changes: 12 additions & 0 deletions tests/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import asyncio
import decimal
import sys
from typing import Optional
from unittest import TestCase
Expand Down Expand Up @@ -28,6 +29,17 @@ def engine_version_lt(version: float) -> bool:
return ENGINE is not None and run_sync(ENGINE.get_version()) < version


def engine_version_gte(version: float) -> bool:
return ENGINE is not None and run_sync(ENGINE.get_version()) > version


def python_version_gte(version: decimal.Decimal) -> bool:
return (
decimal.Decimal(f"{sys.version_info.major}.{sys.version_info.minor}")
>= version
)


def is_running_postgres() -> bool:
return type(ENGINE) is PostgresEngine

Expand Down
45 changes: 38 additions & 7 deletions tests/columns/test_uuid.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,50 @@
import decimal
import uuid

import pytest

from piccolo.columns.column_types import UUID
from piccolo.columns.defaults.uuid import UUID7
from piccolo.table import Table
from piccolo.testing.test_case import TableTest
from piccolo.testing.test_case import AsyncTableTest
from tests.base import (
engine_version_gte,
is_running_postgres,
python_version_gte,
)


class MyTable(Table):
class UUIDTable(Table):
uuid = UUID()


class TestUUID(TableTest):
tables = [MyTable]
class TestUUID(AsyncTableTest):
tables = [UUIDTable]

def test_return_type(self):
row = MyTable()
row.save().run_sync()
async def test_return_type(self):
row = UUIDTable()
await row.save()

self.assertIsInstance(row.uuid, uuid.UUID)


class UUID7Table(Table):
uuid_7 = UUID(default=UUID7())


@pytest.mark.skipif(
not (
python_version_gte(decimal.Decimal("3.14"))
and is_running_postgres()
and engine_version_gte(18)
),
reason="Only Python >= 3.14 and Postgres >= 18 are supported.",
)
class TestUUID7(AsyncTableTest):
tables = [UUID7Table]

async def test_return_type(self):
row = UUID7Table()
await row.save()

self.assertIsInstance(row.uuid_7, uuid.UUID)