|
FORUMS PROFESSIONNELS WINDEV, WEBDEV et WINDEV Mobile |
| | | | | |
| 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()
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
nTimestamp = DateVersChaîne(DateSys(), “YYYYMMDDHHmmSSCC”) nTimestamp = Val(nTimestamp) * 10
nTimestamp = DateHeureVersRéel(DateHeureSys()) * 86400000
sTimestampHex = Droite(“000000000000” + DécimalVersHexa(nTimestamp), 12)
nRandom = Hasard(4096) sRandA = Droite(“000” + DécimalVersHexa(nRandom), 3)
sRandA = “7” + Droite(sRandA, 2)
sRandB = “” POUR i = 1 *À* 15 sRandB += DécimalVersHexa(Hasard(16)) FIN
nRandom = Hasard(4) SELON nRandom CAS 0: sVariant = “8” CAS 1: sVariant = “9” CAS 2: sVariant = “A” CAS 3: sVariant = “B” FIN
sRandB = sVariant + sRandB
sUUID = Gauche(sTimestampHex, 8) + “-” + … Milieu(sTimestampHex, 9, 4) + “-” + … sVersion + Droite(sRandA, 3) + “-” + … Gauche(sRandB, 4) + “-” + … Droite(sRandB, 12)
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
IF NOT ValidateUUIDv7(sUUID) THEN RESULT 0 END
sClean is string = Upper(Replace(sUUID, "-", ""))
sTimestampHex is string = sClean[[1 TO 12]]
nTimestamp is 8-byte int = HexaToInt(sTimestampHex)
RESULT nTimestamp
Procedure UUIDv7ToDateTime(sUUID is string) : DateTime
nMilliseconds is 8-byte int = ExtractTimestampFromUUIDv7(sUUID)
IF nMilliseconds = 0 THEN RESULT "" END
nSeconds is 8-byte int = nMilliseconds / 1000 nMilli is int = nMilliseconds MOD 1000
dtResult is DateTime = UnixToDateTime(nSeconds) dtResult.Millisecond = nMilli
RESULT dtResult
sNewUUID is string = GetUUIDv7() Trace("UUID v7 gerado: " + sNewUUID)
IF ValidateUUIDv7(sNewUUID) THEN Trace("UUID válido!") nTimestamp is 8-byte int = ExtractTimestampFromUUIDv7(sNewUUID) Trace("Timestamp (ms): " + nTimestamp) dtOriginal is DateTime = UUIDv7ToDateTime(sNewUUID) Trace("Data/Hora: " + DateTimeToString(dtOriginal)) ELSE Trace("UUID inválido!") END
Trace("--- Teste de ordenação temporal ---") arrUUIDs is array of strings
FOR i = 1 _TO_ 5 arrUUIDs.Add(GetUUIDv7()) ThreadPause(10) 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() : string
nTimestamp is 8-byte int nRandomA is int nRandomB is 8-byte int sUUID is string dtNow is DateTime nMilliseconds is 8-byte int
dtNow = SysDateTime() nMilliseconds = DateTimeToInteger(dtNow)
nTimestamp = nMilliseconds * 1000
nTimestamp += Right(dtNow..Millisecond, 3)
InitRandom() nRandomA = Random(0, 4095) nRandomB = Random(0, 0x3FFFFFFFFFFFFFFF)
sUUID = DecToHex(BitRightShift(nTimestamp, 32), 8) sUUID += DecToHex(BitAnd(nTimestamp, 0xFFFF0000) / 0x10000, 4)
sUUID += "-" sUUID += "7" sUUID += DecToHex(nRandomA, 3)
sUUID += "-" nVariant is int = BitOr(0x8000, BitAnd(BitRightShift(nRandomB, 48), 0x3FFF)) sUUID += DecToHex(nVariant, 4)
sUUID += "-" sUUID += DecToHex(BitRightShift(BitAnd(nRandomB, 0x0000FFFF00000000), 32), 4) sUUID += DecToHex(BitAnd(nRandomB, 0xFFFFFFFF), 8)
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()
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:
## ?? 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; |
| |
| |
| | | |
|
| | | | |
| | |
| | |
| |
|
|
|