|  | 
| 31 | 31 | #include <utils/builtins.h> | 
| 32 | 32 | #include <utils/catcache.h> | 
| 33 | 33 | #include <utils/date.h> | 
|  | 34 | +#include <utils/elog.h> | 
| 34 | 35 | #include <utils/fmgroids.h> | 
| 35 | 36 | #include <utils/fmgrprotos.h> | 
| 36 | 37 | #include <utils/lsyscache.h> | 
|  | 
| 47 | 48 | #include "jsonb_utils.h" | 
| 48 | 49 | #include "time_utils.h" | 
| 49 | 50 | #include "utils.h" | 
|  | 51 | +#include "uuid.h" | 
|  | 52 | +#include <utils/timestamp.h> | 
|  | 53 | +#include <utils/uuid.h> | 
| 50 | 54 | 
 | 
| 51 | 55 | typedef struct | 
| 52 | 56 | { | 
| @@ -148,7 +152,7 @@ ts_time_value_to_internal(Datum time_val, Oid type_oid) | 
| 148 | 152 | 		elog(ERROR, "unknown time type \"%s\"", format_type_be(type_oid)); | 
| 149 | 153 | 	} | 
| 150 | 154 | 
 | 
| 151 |  | -	if (IS_INTEGER_TYPE(type_oid)) | 
|  | 155 | +	if (IS_INTEGER_TYPE(type_oid) || IS_UUID_TYPE(type_oid)) | 
| 152 | 156 | 	{ | 
| 153 | 157 | 		/* Integer time types have no distinction between min, max and | 
| 154 | 158 | 		 * infinity. We don't want min and max to be turned into infinity for | 
| @@ -189,6 +193,32 @@ ts_time_value_to_internal(Datum time_val, Oid type_oid) | 
| 189 | 193 | 			res = DirectFunctionCall1(ts_pg_timestamp_to_unix_microseconds, tz); | 
| 190 | 194 | 
 | 
| 191 | 195 | 			return DatumGetInt64(res); | 
|  | 196 | +		case UUIDOID: | 
|  | 197 | +		{ | 
|  | 198 | +			uint64 unixtime_ms = 0; | 
|  | 199 | + | 
|  | 200 | +			/* | 
|  | 201 | +			 * Extract the unix timestamp from the UUUID. Note that we cannot | 
|  | 202 | +			 * use the (optional) sub-milliseconds part because there is no | 
|  | 203 | +			 * way to know whether it represents time or is random. | 
|  | 204 | +			 * | 
|  | 205 | +			 * If the UUID is not v7, it doesn't have the expected millisecond | 
|  | 206 | +			 * timestamp either, but we pretend it is a timestamp nevertheless | 
|  | 207 | +			 * since we don't want to error out. | 
|  | 208 | +			 */ | 
|  | 209 | +			if (!ts_uuid_v7_extract_unixtime_ms(DatumGetUUIDP(time_val), &unixtime_ms, NULL)) | 
|  | 210 | +			{ | 
|  | 211 | +				ereport(ERROR, | 
|  | 212 | +						errcode(ERRCODE_FEATURE_NOT_SUPPORTED), | 
|  | 213 | +						errmsg("%s is not version 7 UUID", | 
|  | 214 | +							   DatumGetCString(DirectFunctionCall1(uuid_out, time_val))), | 
|  | 215 | +						errdetail( | 
|  | 216 | +							"UUID \"time\" partitioning columns only support version 7 UUIDs.")); | 
|  | 217 | +			} | 
|  | 218 | + | 
|  | 219 | +			/* Convert to microseconds */ | 
|  | 220 | +			return unixtime_ms * 1000; | 
|  | 221 | +		} | 
| 192 | 222 | 		default: | 
| 193 | 223 | 			elog(ERROR, "unknown time type \"%s\"", format_type_be(type_oid)); | 
| 194 | 224 | 			return -1; | 
| @@ -294,6 +324,31 @@ ts_time_value_to_internal_or_infinite(Datum time_val, Oid type_oid) | 
| 294 | 324 | 
 | 
| 295 | 325 | 			return ts_time_value_to_internal(time_val, type_oid); | 
| 296 | 326 | 		} | 
|  | 327 | +		case UUIDOID: | 
|  | 328 | +		{ | 
|  | 329 | +			uint64 unixtime_ms = 0; | 
|  | 330 | + | 
|  | 331 | +			/* | 
|  | 332 | +			 * Extract the unix timestamp from the UUUID. Note that we cannot | 
|  | 333 | +			 * use the (optional) sub-milliseconds part because there is no | 
|  | 334 | +			 * way to know whether it represents time or is random. | 
|  | 335 | +			 * | 
|  | 336 | +			 * If the UUID is not v7, it doesn't have the expected millisecond | 
|  | 337 | +			 * timestamp either, but we pretend it is a timestamp nevertheless | 
|  | 338 | +			 * since we don't want to error out. | 
|  | 339 | +			 */ | 
|  | 340 | +			if (!ts_uuid_v7_extract_unixtime_ms(DatumGetUUIDP(time_val), &unixtime_ms, NULL)) | 
|  | 341 | +			{ | 
|  | 342 | +				ereport(ERROR, | 
|  | 343 | +						errcode(ERRCODE_FEATURE_NOT_SUPPORTED), | 
|  | 344 | +						errmsg("%s is not version 7 UUID", | 
|  | 345 | +							   DatumGetCString(DirectFunctionCall1(uuid_out, time_val))), | 
|  | 346 | +						errdetail( | 
|  | 347 | +							"UUID \"time\" partitioning columns only support version 7 UUIDs.")); | 
|  | 348 | +			} | 
|  | 349 | + | 
|  | 350 | +			return unixtime_ms * 1000; | 
|  | 351 | +		} | 
| 297 | 352 | 		default: | 
| 298 | 353 | 			return ts_time_value_to_internal(time_val, type_oid); | 
| 299 | 354 | 	} | 
| @@ -338,6 +393,17 @@ ts_internal_to_time_value(int64 value, Oid type) | 
| 338 | 393 | 			return DirectFunctionCall1(ts_pg_unix_microseconds_to_timestamp, Int64GetDatum(value)); | 
| 339 | 394 | 		case DATEOID: | 
| 340 | 395 | 			return DirectFunctionCall1(ts_pg_unix_microseconds_to_date, Int64GetDatum(value)); | 
|  | 396 | +		case UUIDOID: | 
|  | 397 | +		{ | 
|  | 398 | +			/* | 
|  | 399 | +			 * Convert the internal unixtime in ms to a UUID with the | 
|  | 400 | +			 * non-timestamp bits set to zero. We do not set the version | 
|  | 401 | +			 * either, because for ranges we only care about the prefix in | 
|  | 402 | +			 * order to divide the whole UUID space into a set of slices. | 
|  | 403 | +			 */ | 
|  | 404 | +			const pg_uuid_t *uuid = ts_create_uuid_v7_from_unixtime_us(value, true, false); | 
|  | 405 | +			return UUIDPGetDatum(uuid); | 
|  | 406 | +		} | 
| 341 | 407 | 		default: | 
| 342 | 408 | 			if (ts_type_is_int8_binary_compatible(type)) | 
| 343 | 409 | 				return Int64GetDatum(value); | 
| @@ -365,6 +431,7 @@ ts_internal_to_time_int64(int64 value, Oid type) | 
| 365 | 431 | 			return value; | 
| 366 | 432 | 		case TIMESTAMPOID: | 
| 367 | 433 | 		case TIMESTAMPTZOID: | 
|  | 434 | +		case UUIDOID: | 
| 368 | 435 | 			/* we continue ts_time_value_to_internal's incorrect handling of TIMESTAMPs for | 
| 369 | 436 | 			 * compatibility */ | 
| 370 | 437 | 			return DatumGetInt64( | 
|  | 
0 commit comments