|
20 | 20 | #include "utils/fmgrprotos.h"
|
21 | 21 | #include "utils/guc.h"
|
22 | 22 | #include "utils/sortsupport.h"
|
| 23 | +#include "utils/timestamp.h" |
23 | 24 | #include "utils/uuid.h"
|
24 | 25 |
|
25 | 26 | /* sortsupport for uuid */
|
@@ -425,3 +426,66 @@ gen_random_uuid(PG_FUNCTION_ARGS)
|
425 | 426 |
|
426 | 427 | PG_RETURN_UUID_P(uuid);
|
427 | 428 | }
|
| 429 | + |
| 430 | +#define UUIDV1_EPOCH_JDATE 2299161 /* == date2j(1582,10,15) */ |
| 431 | + |
| 432 | +/* |
| 433 | + * Extract timestamp from UUID. |
| 434 | + * |
| 435 | + * Returns null if not RFC 4122 variant or not a version that has a timestamp. |
| 436 | + */ |
| 437 | +Datum |
| 438 | +uuid_extract_timestamp(PG_FUNCTION_ARGS) |
| 439 | +{ |
| 440 | + pg_uuid_t *uuid = PG_GETARG_UUID_P(0); |
| 441 | + int version; |
| 442 | + uint64 tms; |
| 443 | + TimestampTz ts; |
| 444 | + |
| 445 | + /* check if RFC 4122 variant */ |
| 446 | + if ((uuid->data[8] & 0xc0) != 0x80) |
| 447 | + PG_RETURN_NULL(); |
| 448 | + |
| 449 | + version = uuid->data[6] >> 4; |
| 450 | + |
| 451 | + if (version == 1) |
| 452 | + { |
| 453 | + tms = ((uint64) uuid->data[0] << 24) |
| 454 | + + ((uint64) uuid->data[1] << 16) |
| 455 | + + ((uint64) uuid->data[2] << 8) |
| 456 | + + ((uint64) uuid->data[3]) |
| 457 | + + ((uint64) uuid->data[4] << 40) |
| 458 | + + ((uint64) uuid->data[5] << 32) |
| 459 | + + (((uint64) uuid->data[6] & 0xf) << 56) |
| 460 | + + ((uint64) uuid->data[7] << 48); |
| 461 | + |
| 462 | + /* convert 100-ns intervals to us, then adjust */ |
| 463 | + ts = (TimestampTz) (tms / 10) - |
| 464 | + ((uint64) POSTGRES_EPOCH_JDATE - UUIDV1_EPOCH_JDATE) * SECS_PER_DAY * USECS_PER_SEC; |
| 465 | + |
| 466 | + PG_RETURN_TIMESTAMPTZ(ts); |
| 467 | + } |
| 468 | + |
| 469 | + /* not a timestamp-containing UUID version */ |
| 470 | + PG_RETURN_NULL(); |
| 471 | +} |
| 472 | + |
| 473 | +/* |
| 474 | + * Extract UUID version. |
| 475 | + * |
| 476 | + * Returns null if not RFC 4122 variant. |
| 477 | + */ |
| 478 | +Datum |
| 479 | +uuid_extract_version(PG_FUNCTION_ARGS) |
| 480 | +{ |
| 481 | + pg_uuid_t *uuid = PG_GETARG_UUID_P(0); |
| 482 | + uint16 version; |
| 483 | + |
| 484 | + /* check if RFC 4122 variant */ |
| 485 | + if ((uuid->data[8] & 0xc0) != 0x80) |
| 486 | + PG_RETURN_NULL(); |
| 487 | + |
| 488 | + version = uuid->data[6] >> 4; |
| 489 | + |
| 490 | + PG_RETURN_UINT16(version); |
| 491 | +} |
0 commit comments