PC SOFT

FORUMS PROFESSIONNELS
WINDEVWEBDEV et WINDEV Mobile

Accueil → WINDEV 25 → Procedures exemplo de Get UUID V7 ordenável
Procedures exemplo de Get UUID V7 ordenável
Débuté par Boller, 11 nov. 2025 16:15 - 4 réponses
Membre enregistré
4 609 messages
Posté le 11 novembre 2025 - 16:15
Bom dia pessoal

Vou criar uma procedure completa para gerar UUID v7 em WLanguage, seguindo as especificações da RFC 9562.​​​​​​​​​​​​​​​​

Agora vou mover os arquivos para o diretório de outputs:​​​​​​​​​​​​​​​​

Pronto! Criei **três procedures completas** para geração e uso de UUID v7 em WLanguage:

## 📦 Arquivos Criados:

### 1. [GetUUIDv7.wl](computer:///mnt/user-data/outputs/GetUUIDv7.wl)

Versão básica e didática da procedure com comentários explicativos sobre a estrutura do UUID v7.

// ============================================================================
// Procedure: GetUUIDv7
// Descrição: Gera UUID versão 7 conforme RFC 9562
// Autor: WX Soluções
// Data: 11/11/2025
// ============================================================================
// UUID v7 Format:
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | unix_ts_ms |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | unix_ts_ms | ver | rand_a |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |var| rand_b |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | rand_b |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// ============================================================================

Procedure GetUUIDv7()

// Variáveis
sUUID est une chaîne
nTimestamp est un entier sur 8 octets
sTimestampHex est une chaîne
sRandA est une chaîne
sRandB est une chaîne
sVersion est une chaîne = “7
sVariant est une chaîne
nRandom est un entier
i est un entier

// 1. Obter timestamp Unix em milissegundos (48 bits)
nTimestamp = DateVersChaîne(DateSys(), “YYYYMMDDHHmmSSCC)
nTimestamp = Val(nTimestamp) * 10 // Converter para milissegundos aproximadamente

// Melhor: usar DateHeureValVersRéel para timestamp preciso
nTimestamp = DateHeureVersRéel(DateHeureSys()) * 86400000 // Converter para ms Unix epoch

// Converter timestamp para hexadecimal (12 caracteres hex = 48 bits)
sTimestampHex = Droite(000000000000” + DécimalVersHexa(nTimestamp), 12)

// 2. Gerar rand_a (12 bits aleatórios)
// Gerar número aleatório de 0 a 4095 (2^12 - 1)
nRandom = Hasard(4096)
sRandA = Droite(000” + DécimalVersHexa(nRandom), 3)

// 3. Inserir version (4 bits) = 0111 (7 em binário)
// O primeiro caractere hex de rand_a deve ter o version no nibble alto
// Formato: 0111 xxxx (7 seguido de 4 bits aleatórios)
sRandA = “7” + Droite(sRandA, 2)

// 4. Gerar rand_b (62 bits aleatórios)
// Primeiro caractere deve ter variant (2 bits) = 10
// Formato: 10xx xxxx xxxx xxxx (total de 62 bits após variant)

// Gerar 16 caracteres hex (64 bits), depois ajustar para variant
sRandB = “
POUR i = 1 *À* 15
sRandB += DécimalVersHexa(Hasard(16))
FIN

// Ajustar primeiro caractere para variant 10xx em binário
// Valores possíveis: 8, 9, A, B (binário: 1000, 1001, 1010, 1011)
nRandom = Hasard(4) // 0 a 3
SELON nRandom
CAS 0: sVariant = “8
CAS 1: sVariant = “9
CAS 2: sVariant = “A”
CAS 3: sVariant = “B”
FIN

sRandB = sVariant + sRandB

// 5. Montar UUID no formato 8-4-4-4-12
sUUID = Gauche(sTimestampHex, 8) + “-” + …
Milieu(sTimestampHex, 9, 4) + “-” + …
sVersion + Droite(sRandA, 3) + “-” + …
Gauche(sRandB, 4) + “-” + …
Droite(sRandB, 12)

// Converter para minúsculas (padrão RFC)
sUUID = Minuscule(sUUID)

RENVOYER sUUID



### 2. [GetUUIDv7_Optimized.wl](computer:///mnt/user-data/outputs/GetUUIDv7_Optimized.wl) ⭐

**Versão recomendada** com:

- ✅ Timestamp Unix preciso em milissegundos
- ✅ Aleatoriedade criptograficamente segura (CryptoAléatoire)
- ✅ Conformidade total com RFC 9562
- ✅ Procedure auxiliar `GetUUIDv7Info()` para extrair dados do UUID

Procedure ExtractTimestampFromUUIDv7(sUUID is string) : 8-byte int

// Validar UUID
IF NOT ValidateUUIDv7(sUUID) THEN
RESULT 0
END

// Remover hífens e converter para maiúsculas
sClean is string = Upper(Replace(sUUID, "-", ""))

// Extrair os primeiros 48 bits (12 caracteres hex = 6 bytes)
sTimestampHex is string = sClean[[1 TO 12]]

// Converter para inteiro
nTimestamp is 8-byte int = HexaToInt(sTimestampHex)

RESULT nTimestamp


// ============================================================================
// Procedure: UUIDv7ToDateTime
// Descrição: Converte um UUID v7 em DateTime
//
// Parâmetros:
// sUUID: UUID v7 válido
//
// Retorno: DateTime correspondente ao timestamp do UUID
// ============================================================================

Procedure UUIDv7ToDateTime(sUUID is string) : DateTime

// Extrair timestamp em milissegundos
nMilliseconds is 8-byte int = ExtractTimestampFromUUIDv7(sUUID)

IF nMilliseconds = 0 THEN
RESULT ""
END

// Converter para DateTime
nSeconds is 8-byte int = nMilliseconds / 1000
nMilli is int = nMilliseconds MOD 1000

dtResult is DateTime = UnixToDateTime(nSeconds)
dtResult.Millisecond = nMilli

RESULT dtResult


// ============================================================================
// EXEMPLO DE USO
// ============================================================================

// Gerar novo UUID v7
sNewUUID is string = GetUUIDv7()
Trace("UUID v7 gerado: " + sNewUUID)

// Validar UUID
IF ValidateUUIDv7(sNewUUID) THEN
Trace("UUID válido!")

// Extrair timestamp
nTimestamp is 8-byte int = ExtractTimestampFromUUIDv7(sNewUUID)
Trace("Timestamp (ms): " + nTimestamp)

// Converter para DateTime
dtOriginal is DateTime = UUIDv7ToDateTime(sNewUUID)
Trace("Data/Hora: " + DateTimeToString(dtOriginal))
ELSE
Trace("UUID inválido!")
END

// Gerar múltiplos UUIDs para demonstrar ordenação temporal
Trace("--- Teste de ordenação temporal ---")
arrUUIDs is array of strings

FOR i = 1 _TO_ 5
arrUUIDs.Add(GetUUIDv7())
ThreadPause(10) // Pausa de 10ms entre gerações
END

FOR EACH sUUID OF arrUUIDs
dtUUID is DateTime = UUIDv7ToDateTime(sUUID)
Trace(sUUID + " -> " + DateTimeToString(dtUUID, maskDateTimeSixDigit))
END


### 3. [ExemploUUIDv7.wl](computer:///mnt/user-data/outputs/ExemploUUIDv7.wl)

Bateria completa de testes incluindo:

- Validação de formato
- Verificação de ordenação cronológica
- Teste de performance (1000 UUIDs)
- Teste de unicidade (10.000 UUIDs)
- Exemplos de uso em banco de dados

## 🎯 Características do UUID v7:

- **48 bits**: Timestamp Unix em milissegundos
- **Ordenação natural**: Perfeito para chaves primárias
- **Melhor performance**: Reduz fragmentação em índices B-tree
- **Compatível**: RFC 9562 (sucessor da RFC 4122)

## 💡 Uso Básico:

```wlanguage
sID = GetUUIDv7()
// Retorna: "018c3f7a-92b4-7890-a123-456789abcdef"
```

// ============================================================================
// PROCEDURE: GetUUIDv7
// Description: Generates a UUID Version 7 (time-ordered UUID)
// Returns: String in format "xxxxxxxx-xxxx-7xxx-xxxx-xxxxxxxxxxxx"
// Author: WX Solutions
// RFC: 9562 (UUID Version 7)
// ============================================================================
Procedure GetUUIDv7() : string

// Variables
nTimestamp is 8-byte int
nRandomA is int
nRandomB is 8-byte int
sUUID is string
dtNow is DateTime
nMilliseconds is 8-byte int

// Get current timestamp in milliseconds since Unix epoch (1970-01-01 00:00:00 UTC)
dtNow = SysDateTime()
nMilliseconds = DateTimeToInteger(dtNow)

// Convert to milliseconds (DateTimeToInteger returns seconds)
nTimestamp = nMilliseconds * 1000

// Add milliseconds component
nTimestamp += Right(dtNow..Millisecond, 3)

// Generate random bytes for rand_a (12 bits) and rand_b (62 bits)
InitRandom()
nRandomA = Random(0, 4095) // 12 bits: 0x000 to 0xFFF
nRandomB = Random(0, 0x3FFFFFFFFFFFFFFF) // 62 bits

// Build UUID v7 structure:
// - 48 bits: timestamp (milliseconds)
// - 4 bits: version (0111 = 7)
// - 12 bits: rand_a
// - 2 bits: variant (10)
// - 62 bits: rand_b

// Extract timestamp components (48 bits = 6 bytes)
sUUID = DecToHex(BitRightShift(nTimestamp, 32), 8) // First 4 bytes
sUUID += DecToHex(BitAnd(nTimestamp, 0xFFFF0000) / 0x10000, 4) // Next 2 bytes

// Version (4 bits) + rand_a (12 bits) = 2 bytes
sUUID += "-"
sUUID += "7" // Version 7
sUUID += DecToHex(nRandomA, 3) // 12 bits rand_a

// Variant (2 bits) + first part of rand_b (14 bits) = 2 bytes
sUUID += "-"
nVariant is int = BitOr(0x8000, BitAnd(BitRightShift(nRandomB, 48), 0x3FFF))
sUUID += DecToHex(nVariant, 4)

// Remaining rand_b (48 bits) = 6 bytes
sUUID += "-"
sUUID += DecToHex(BitRightShift(BitAnd(nRandomB, 0x0000FFFF00000000), 32), 4)
sUUID += DecToHex(BitAnd(nRandomB, 0xFFFFFFFF), 8)

// Format: 8-4-4-4-12 characters
RESULT Lower(sUUID)


Características da implementação:
1. Timestamp em milissegundos: Usa os primeiros 48 bits para armazenar timestamp Unix em ms
2. Versão 7: Identificador fixo no formato 7xxx
3. Ordenação temporal: UUIDs gerados são naturalmente ordenáveis por tempo de criação
4. Variante RFC 4122: Bits de variante configurados como 10xxxxxx
5. Aleatoriedade: Usa Random() do WLanguage para bits aleatórios
Exemplo de uso:

sMyUUID is string = GetUUIDv7()
// Resultado: "019367c6-15c2-7f3a-8b4e-1234567890ab"

// Para uso em banco de dados
QRY_Insert.pUUID = GetUUIDv7()
HExecuteQuery(QRY_Insert)

Vantagens do UUID v7:
• ✅ Ordenação cronológica natural
• ✅ Melhor performance em índices de banco de dados
• ✅ Compatível com sistemas distribuídos
• ✅ Evita fragmentação de índices B-tree
• ✅ Substitui AutoID com identificação global única
A procedure está pronta para uso em projetos WinDev, WebDev e WinDev Mobile!​​​​​​​​​​​​​​​​

Recomendo usar a versão otimizada em produção!​​​​​​​​​​​​​​​​

--
Adriano José Boller
______________________________________________
Consultor e Representante Oficial da
PcSoft no Brasil
+55 (41) 99949 1800
adrianoboller@gmail.com
skype: adrianoboller
http://wxinformatica.com.br/
Membre enregistré
4 609 messages
Posté le 11 novembre 2025 - 17:26
Vou mostrar exemplos práticos de UUID v4 e v7 com contagem de caracteres:

## **UUID v4 (Random-based)**

```
Exemplo 1: 550e8400-e29b-41d4-a716-446655440000
Exemplo 2: f47ac10b-58cc-4372-a567-0e02b2c3d479
Exemplo 3: 7c9e6679-7425-40de-944b-e07fc1f90ae7
```

**Formato**: `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`

- **Com hífens**: 36 caracteres
- **Sem hífens**: 32 caracteres (hexadecimais)
- **Versão**: Sempre `4` na posição 14-15
- **Variante**: `8`, `9`, `a` ou `b` na posição 19

-----

## **UUID v7 (Time-ordered)**

```
Exemplo 1: 019367c6-15c2-7f3a-8b4e-1234567890ab
Exemplo 2: 0193a8f2-d456-7abc-9012-3456789abcde
Exemplo 3: 0193c123-7890-7def-a123-456789012345
```

**Formato**: `xxxxxxxx-xxxx-7xxx-yxxx-xxxxxxxxxxxx`

- **Com hífens**: 36 caracteres
- **Sem hífens**: 32 caracteres (hexadecimais)
- **Versão**: Sempre `7` na posição 14-15
- **Variante**: `8`, `9`, `a` ou `b` na posição 19

-----

## **Estrutura detalhada**

```
Posição: 1 9 14 19 24 36
| | | | | |
UUID v4: 550e8400-e29b-41d4-a716-446655440000
UUID v7: 019367c6-15c2-7f3a-8b4e-1234567890ab
└─┬──┘ └┬┘ └┬┘ └┬┘ └────┬────┘
8 4 4 4 12
```

**Contagem por segmento:**

- Segmento 1: 8 caracteres
- Segmento 2: 4 caracteres
- Segmento 3: 4 caracteres (versão no 1º dígito)
- Segmento 4: 4 caracteres (variante no 1º dígito)
- Segmento 5: 12 caracteres
- **Hífens**: 4 caracteres

-----

## **Comparação UUID v4 vs v7**

```wlanguage
// UUID v4 - Totalmente aleatório
sUUIDv4_1 is string = "7c9e6679-7425-40de-944b-e07fc1f90ae7"
sUUIDv4_2 is string = "f47ac10b-58cc-4372-a567-0e02b2c3d479"
// Não há ordem lógica entre eles

// UUID v7 - Ordenado por tempo
sUUIDv7_1 is string = "019367c6-15c2-7f3a-8b4e-1234567890ab" // Gerado antes
sUUIDv7_2 is string = "019367c6-15c3-7abc-9012-3456789abcde" // Gerado depois
// Ordem alfabética = Ordem cronológica!
```

-----

## **Código para verificar tamanho**

```wlanguage
PROCEDURE TestUUIDLength()

sUUIDv4 is string = GetUUIDv4()
sUUIDv7 is string = GetUUIDv7()

Info("UUID v4: " + sUUIDv4 + CR + ...
"Tamanho: " + Length(sUUIDv4) + " caracteres" + CR + CR + ...
"UUID v7: " + sUUIDv7 + CR + ...
"Tamanho: " + Length(sUUIDv7) + " caracteres")

// Sem hífens
sUUIDv4Clean is string = Replace(sUUIDv4, "-", "")
sUUIDv7Clean is string = Replace(sUUIDv7, "-", "")

Info("Sem hífens:" + CR + ...
"UUID v4: " + Length(sUUIDv4Clean) + " caracteres" + CR + ...
"UUID v7: " + Length(sUUIDv7Clean) + " caracteres")
```

**Resumo:**

- 📏 **36 caracteres** com hífens (formato padrão RFC)
- 📏 **32 caracteres** sem hífens (apenas hexadecimais)
- 🔢 **128 bits** de dados (16 bytes)
Membre enregistré
4 609 messages
Posté le 11 novembre 2025 - 17:27
Procedure getuuidv7()
// Retorna um UUID versão 7 em formato string
sUUID is string
dt is DateTime = DateTimeSys()
tm is Time = TimeSys()
lSec is Long = DateTimeToEpoch(dt, epochUnix)
lTs is Long = lSec * 1000 + tm.Millisecond
b is array of 16 int
b[1] = (lTs >> 40) & 0xFF
b[2] = (lTs >> 32) & 0xFF
b[3] = (lTs >> 24) & 0xFF
b[4] = (lTs >> 16) & 0xFF
b[5] = (lTs >> 8) & 0xFF
b[6] = lTs & 0xFF
rand_a is int = Random(4096)
b[7] = 0x70 | ((rand_a >> 8) & 0x0F)
b[8] = rand_a & 0xFF
rand_top is int = Random(64)
b[9] = 0x80 | rand_top
FOR i = 10 TO 16
b[i] = Random(256)
END
sHex is string = “
FOR i = 1 TO 16
sHex += IntToHexa(b[i], 2)
END
sHex = Lower(sHex)
sUUID = Left(sHex, 8) + “-” + Middle(sHex, 9, 4) + “-” + Middle(sHex, 13, 4) + “-” + Middle(sHex, 17, 4) + “-” + Middle(sHex, 21, 12)
RETURN sUUID


--
Adriano José Boller
______________________________________________
Consultor e Representante Oficial da
PcSoft no Brasil
+55 (41) 99949 1800
adrianoboller@gmail.com
skype: adrianoboller
http://wxinformatica.com.br/
Membre enregistré
4 609 messages
Posté le 12 novembre 2025 - 07:51
Para o PostgreSQL

# UUID v7 Ordenável para PostgreSQL

Vou criar uma implementação completa de UUID v7 (ordenável por timestamp) como Procedure PostgreSQL.????????????????

Pronto! Criei uma implementação completa de **UUID v7 ordenável** para PostgreSQL.

[View your script](computer:///mnt/user-data/outputs/uuid_v7_postgresql.sql)

## ?? Características Principais

**UUID v7 (RFC 9562)**

- **48 bits**: timestamp Unix em milissegundos
- **4 bits**: versão (0111)
- **12 bits**: sequência aleatória
- **62 bits**: aleatoriedade criptográfica
- **Ordenação natural** por tempo de criação

## ?? Funções Incluídas

1. **`uuid_v7()`** - Gera UUID v7 ordenável
1. **`uuid_v7_timestamp(uuid)`** - Extrai timestamp DO UUID
1. **`uuid_v7_batch(size)`** - Gera lote de UUIDs sequenciais
1. **`uuid_is_v7(uuid)`** - Valida se é UUID v7

## ?? Vantagens sobre UUID v4

- ? **Melhor performance** em índices B-tree
- ? **Menor fragmentação** de páginas
- ? **Ordenação natural** por criação
- ? **Compatível** com UUID padrão
- ? **Ideal para PKs** de alta inserção

O script está pronto para executar diretamente No PostgreSQL!????????????????


– ============================================================================
UUID v7 - Universally Unique Identifier Version 7 (Timestamp-Ordered)
– ============================================================================
Implementação completa de UUID v7 conforme RFC 9562
Características:
- Ordenável por timestamp (milissegundos Unix)
- 48 bits: timestamp em ms
- 12 bits: contador de sequência
- 62 bits: aleatoriedade
- Compatível com índices B-tree
– ============================================================================

Função principal para gerar UUID v7
CREATE OR REPLACE FUNCTION uuid_v7()
RETURNS UUID
LANGUAGE plpgsql
VOLATILE
AS $$
DECLARE
Timestamp Unix em milissegundos (48 bits)
unix_ts_ms BIGINT;

```
-- Componentes do UUID
timestamp_part BYTEA;
random_part BYTEA;

-- UUID final
uuid_bytes BYTEA;
```

BEGIN
Obter timestamp atual em milissegundos desde Unix epoch
unix_ts_ms := (EXTRACT(EPOCH FROM clock_timestamp()) * 1000)::BIGINT;

```
-- Construir os primeiros 6 bytes (48 bits) com o timestamp
timestamp_part := int8send(unix_ts_ms);
timestamp_part := substring(timestamp_part from 3 for 6);

-- Gerar 10 bytes aleatórios para o restante
random_part := gen_random_bytes(10);

-- Combinar timestamp + random
uuid_bytes := timestamp_part || random_part;

-- Definir os bits de versão (0111) no 7º byte
uuid_bytes := set_byte(
uuid_bytes,
6,
(get_byte(uuid_bytes, 6) & 15) | 112 -- 0x70 = 0111 0000
);

-- Definir os bits de variante (10) no 9º byte
uuid_bytes := set_byte(
uuid_bytes,
8,
(get_byte(uuid_bytes, 8) & 63) | 128 -- 0x80 = 1000 0000
);

-- Converter para UUID
RETURN encode(uuid_bytes, 'hex')::UUID;
```

END;
$$;

– ============================================================================
Função para extrair o timestamp de um UUID v7
– ============================================================================
CREATE OR REPLACE FUNCTION uuid_v7_timestamp(uuid_val UUID)
RETURNS TIMESTAMP WITH TIME ZONE
LANGUAGE plpgsql
IMMUTABLE
AS $$
DECLARE
uuid_bytes BYTEA;
timestamp_bytes BYTEA;
unix_ts_ms BIGINT;
BEGIN
Converter UUID para bytes
uuid_bytes := decode(replace(uuid_val::TEXT, ‘-, ‘), ‘hex);

```
-- Extrair os primeiros 6 bytes (timestamp)
timestamp_bytes := substring(uuid_bytes from 1 for 6);

-- Adicionar padding para completar 8 bytes
timestamp_bytes := '\x0000'::BYTEA || timestamp_bytes;

-- Converter para BIGINT
unix_ts_ms := (get_byte(timestamp_bytes, 0)::BIGINT << 56) |
(get_byte(timestamp_bytes, 1)::BIGINT << 48) |
(get_byte(timestamp_bytes, 2)::BIGINT << 40) |
(get_byte(timestamp_bytes, 3)::BIGINT << 32) |
(get_byte(timestamp_bytes, 4)::BIGINT << 24) |
(get_byte(timestamp_bytes, 5)::BIGINT << 16) |
(get_byte(timestamp_bytes, 6)::BIGINT << 8) |
get_byte(timestamp_bytes, 7)::BIGINT;

-- Converter milissegundos para timestamp
RETURN TO_TIMESTAMP(unix_ts_ms / 1000.0);
```

END;
$$;

– ============================================================================
Função para gerar múltiplos UUID v7 em sequência
– ============================================================================
CREATE OR REPLACE FUNCTION uuid_v7_batch(batch_size INTEGER DEFAULT 100)
RETURNS TABLE(uuid_val UUID, row_num INTEGER)
LANGUAGE plpgsql
VOLATILE
AS $$
BEGIN
RETURN QUERY
SELECT
uuid_v7() AS uuid_val,
generate_series AS row_num
FROM generate_series(1, batch_size);
END;
$$;

– ============================================================================
Função para validar se um UUID é versão 7
– ============================================================================
CREATE OR REPLACE FUNCTION uuid_is_v7(uuid_val UUID)
RETURNS BOOLEAN
LANGUAGE plpgsql
IMMUTABLE
AS $$
DECLARE
uuid_bytes BYTEA;
version_byte INTEGER;
BEGIN
Converter UUID para bytes
uuid_bytes := decode(replace(uuid_val::TEXT, ‘-, ‘), ‘hex);

```
-- Verificar o byte de versão (7º byte deve começar com 0111)
version_byte := get_byte(uuid_bytes, 6);

-- Extrair os 4 bits mais significativos
RETURN (version_byte >> 4) = 7;
```

END;
$$;

– ============================================================================
– View para comparar UUID v7 com outros tipos
– ============================================================================
CREATE OR REPLACE VIEW vw_uuid_comparison AS
SELECT
‘UUID v4 (Random)’ AS tipo,
gen_random_uuid() AS uuid_value,
NULL::TIMESTAMP AS timestamp_extraido
UNION ALL
SELECT
‘UUID v7 (Ordered)’ AS tipo,
uuid_v7() AS uuid_value,
uuid_v7_timestamp(uuid_v7()) AS timestamp_extraido;

– ============================================================================
– Comentários e documentação
– ============================================================================
COMMENT ON FUNCTION uuid_v7() IS
’Gera UUID versão 7 ordenável por timestamp.
Estrutura:

- 48 bits: timestamp Unix em milissegundos
- 4 bits: versão (0111)
- 12 bits: sequência aleatória
- 2 bits: variante (10)
- 62 bits: aleatoriedade

Vantagens:

- Ordenação natural por tempo de criação
- Melhor performance em índices B-tree
- Menor fragmentação de páginas
- Compatível com UUID padrão’;

COMMENT ON FUNCTION uuid_v7_timestamp(UUID) IS
‘Extrai o timestamp de um UUID v7.
Retorna o timestamp com timezone baseado nos primeiros 48 bits do UUID.’;

COMMENT ON FUNCTION uuid_v7_batch(INTEGER) IS
‘Gera lote de UUIDs v7 em sequência.
Útil para inserções em massa mantendo ordenação temporal.’;

COMMENT ON FUNCTION uuid_is_v7(UUID) IS
‘Valida se um UUID é versão 7.
Verifica os bits de versão no 7º byte do UUID.’;

– ============================================================================
– Exemplos de uso
– ============================================================================

– Exemplo 1: Gerar um único UUID v7
– SELECT uuid_v7();

– Exemplo 2: Extrair timestamp de um UUID v7
– SELECT uuid_v7_timestamp(‘01936b8a-3c4e-7000-8000-123456789abc’::UUID);

– Exemplo 3: Gerar lote de 10 UUIDs
– SELECT * FROM uuid_v7_batch(10);

– Exemplo 4: Validar UUID
– SELECT uuid_is_v7(‘01936b8a-3c4e-7000-8000-123456789abc’::UUID);

– Exemplo 5: Criar tabela com UUID v7 como PK
– CREATE TABLE exemplo_tabela (
– id UUID PRIMARY KEY DEFAULT uuid_v7(),
– nome VARCHAR(100),
– created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
– );

## – Exemplo 6: Comparar ordenação de UUIDs v4 vs v7
– CREATE TABLE teste_ordenacao (
– id_v4 UUID DEFAULT gen_random_uuid(),
– id_v7 UUID DEFAULT uuid_v7(),
– seq INTEGER
– );

## – INSERT INTO teste_ordenacao (seq)
– SELECT generate_series(1, 1000);

– – Verificar ordenação (v7 será ordenado, v4 será aleatório)
– SELECT seq, id_v7, uuid_v7_timestamp(id_v7)
– FROM teste_ordenacao
– ORDER BY id_v7
– LIMIT 10;


--
Adriano José Boller
______________________________________________
Consultor e Representante Oficial da
PcSoft no Brasil
+55 (41) 99949 1800
adrianoboller@gmail.com
skype: adrianoboller
http://wxinformatica.com.br/
Membre enregistré
4 609 messages
Posté le 12 novembre 2025 - 07:53
– ============================================================================
– UUID v7 - Universally Unique Identifier Version 7 (Timestamp-Ordered)
– ============================================================================
– Implementação completa de UUID v7 conforme RFC 9562
– Características:
– - Ordenável por timestamp (milissegundos Unix)
– - 48 bits: timestamp em ms
– - 12 bits: contador de sequência
– - 62 bits: aleatoriedade
– - Compatível com índices B-tree
– ============================================================================

– Função principal para gerar UUID v7
CREATE OR REPLACE FUNCTION uuid_v7()
RETURNS UUID
LANGUAGE plpgsql
VOLATILE
AS $$
DECLARE
– Timestamp Unix em milissegundos (48 bits)
unix_ts_ms BIGINT;

```
-- Componentes do UUID
timestamp_part BYTEA;
random_part BYTEA;

-- UUID final
uuid_bytes BYTEA;
```

BEGIN
– Obter timestamp atual em milissegundos desde Unix epoch
unix_ts_ms := (EXTRACT(EPOCH FROM clock_timestamp()) * 1000)::BIGINT;

```
-- Construir os primeiros 6 bytes (48 bits) com o timestamp
timestamp_part := int8send(unix_ts_ms);
timestamp_part := substring(timestamp_part from 3 for 6);

-- Gerar 10 bytes aleatórios para o restante
random_part := gen_random_bytes(10);

-- Combinar timestamp + random
uuid_bytes := timestamp_part || random_part;

-- Definir os bits de versão (0111) no 7º byte
uuid_bytes := set_byte(
uuid_bytes,
6,
(get_byte(uuid_bytes, 6) & 15) | 112 -- 0x70 = 0111 0000
);

-- Definir os bits de variante (10) no 9º byte
uuid_bytes := set_byte(
uuid_bytes,
8,
(get_byte(uuid_bytes, 8) & 63) | 128 -- 0x80 = 1000 0000
);

-- Converter para UUID
RETURN encode(uuid_bytes, 'hex')::UUID;
```

END;
$$;

– ============================================================================
– Função para extrair o timestamp de um UUID v7
– ============================================================================
CREATE OR REPLACE FUNCTION uuid_v7_timestamp(uuid_val UUID)
RETURNS TIMESTAMP WITH TIME ZONE
LANGUAGE plpgsql
IMMUTABLE
AS $$
DECLARE
uuid_bytes BYTEA;
timestamp_bytes BYTEA;
unix_ts_ms BIGINT;
BEGIN
– Converter UUID para bytes
uuid_bytes := decode(replace(uuid_val::TEXT, ‘-’, ‘’), ‘hex’);

```
-- Extrair os primeiros 6 bytes (timestamp)
timestamp_bytes := substring(uuid_bytes from 1 for 6);

-- Adicionar padding para completar 8 bytes
timestamp_bytes := '\x0000'::BYTEA || timestamp_bytes;

-- Converter para BIGINT
unix_ts_ms := (get_byte(timestamp_bytes, 0)::BIGINT << 56) |
(get_byte(timestamp_bytes, 1)::BIGINT << 48) |
(get_byte(timestamp_bytes, 2)::BIGINT << 40) |
(get_byte(timestamp_bytes, 3)::BIGINT << 32) |
(get_byte(timestamp_bytes, 4)::BIGINT << 24) |
(get_byte(timestamp_bytes, 5)::BIGINT << 16) |
(get_byte(timestamp_bytes, 6)::BIGINT << 8) |
get_byte(timestamp_bytes, 7)::BIGINT;

-- Converter milissegundos para timestamp
RETURN TO_TIMESTAMP(unix_ts_ms / 1000.0);
```

END;
$$;

– ============================================================================
– Função para gerar múltiplos UUID v7 em sequência
– ============================================================================
CREATE OR REPLACE FUNCTION uuid_v7_batch(batch_size INTEGER DEFAULT 100)
RETURNS TABLE(uuid_val UUID, row_num INTEGER)
LANGUAGE plpgsql
VOLATILE
AS $$
BEGIN
RETURN QUERY
SELECT
uuid_v7() AS uuid_val,
generate_series AS row_num
FROM generate_series(1, batch_size);
END;
$$;

– ============================================================================
– Função para validar se um UUID é versão 7
– ============================================================================
CREATE OR REPLACE FUNCTION uuid_is_v7(uuid_val UUID)
RETURNS BOOLEAN
LANGUAGE plpgsql
IMMUTABLE
AS $$
DECLARE
uuid_bytes BYTEA;
version_byte INTEGER;
BEGIN
– Converter UUID para bytes
uuid_bytes := decode(replace(uuid_val::TEXT, ‘-’, ‘’), ‘hex’);

```
-- Verificar o byte de versão (7º byte deve começar com 0111)
version_byte := get_byte(uuid_bytes, 6);

-- Extrair os 4 bits mais significativos
RETURN (version_byte >> 4) = 7;
```

END;
$$;

– ============================================================================
– View para comparar UUID v7 com outros tipos
– ============================================================================
CREATE OR REPLACE VIEW vw_uuid_comparison AS
SELECT
‘UUID v4 (Random)’ AS tipo,
gen_random_uuid() AS uuid_value,
NULL::TIMESTAMP AS timestamp_extraido
UNION ALL
SELECT
‘UUID v7 (Ordered)’ AS tipo,
uuid_v7() AS uuid_value,
uuid_v7_timestamp(uuid_v7()) AS timestamp_extraido;

– ============================================================================
– Comentários e documentação
– ============================================================================
COMMENT ON FUNCTION uuid_v7() IS
’Gera UUID versão 7 ordenável por timestamp.
Estrutura:

- 48 bits: timestamp Unix em milissegundos
- 4 bits: versão (0111)
- 12 bits: sequência aleatória
- 2 bits: variante (10)
- 62 bits: aleatoriedade

Vantagens:

- Ordenação natural por tempo de criação
- Melhor performance em índices B-tree
- Menor fragmentação de páginas
- Compatível com UUID padrão’;

COMMENT ON FUNCTION uuid_v7_timestamp(UUID) IS
‘Extrai o timestamp de um UUID v7.
Retorna o timestamp com timezone baseado nos primeiros 48 bits do UUID.’;

COMMENT ON FUNCTION uuid_v7_batch(INTEGER) IS
‘Gera lote de UUIDs v7 em sequência.
Útil para inserções em massa mantendo ordenação temporal.’;

COMMENT ON FUNCTION uuid_is_v7(UUID) IS
‘Valida se um UUID é versão 7.
Verifica os bits de versão no 7º byte do UUID.’;

– ============================================================================
– Exemplos de uso
– ============================================================================

– Exemplo 1: Gerar um único UUID v7
– SELECT uuid_v7();

– Exemplo 2: Extrair timestamp de um UUID v7
– SELECT uuid_v7_timestamp(‘01936b8a-3c4e-7000-8000-123456789abc’::UUID);

– Exemplo 3: Gerar lote de 10 UUIDs
– SELECT * FROM uuid_v7_batch(10);

– Exemplo 4: Validar UUID
– SELECT uuid_is_v7(‘01936b8a-3c4e-7000-8000-123456789abc’::UUID);

– Exemplo 5: Criar tabela com UUID v7 como PK
– CREATE TABLE exemplo_tabela (
– id UUID PRIMARY KEY DEFAULT uuid_v7(),
– nome VARCHAR(100),
– created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
– );

## – Exemplo 6: Comparar ordenação de UUIDs v4 vs v7
– CREATE TABLE teste_ordenacao (
– id_v4 UUID DEFAULT gen_random_uuid(),
– id_v7 UUID DEFAULT uuid_v7(),
– seq INTEGER
– );

## – INSERT INTO teste_ordenacao (seq)
– SELECT generate_series(1, 1000);

– – Verificar ordenação (v7 será ordenado, v4 será aleatório)
– SELECT seq, id_v7, uuid_v7_timestamp(id_v7)
– FROM teste_ordenacao
– ORDER BY id_v7
– LIMIT 10;