diff --git a/src/results/resultUtils.ts b/src/results/resultUtils.ts index e152095..b02c8aa 100644 --- a/src/results/resultUtils.ts +++ b/src/results/resultUtils.ts @@ -270,6 +270,8 @@ export function convertValue( } }); } + case 'UUID': + return toUuid(Array.from(value)); case 'Unknown': return value && value.toJSON ? value.toJSON() : value; } @@ -297,6 +299,7 @@ export function getDisplayValue( switch (val.type) { case 'String': + case 'UUID': return JSON.stringify(val.value); case 'Bool': return val.value ? 'true' : 'false'; @@ -410,6 +413,21 @@ function uint128ToBigInt(tuple: bigint[]) { return (BigInt.asUintN(64, tuple[1]) << BigInt(64)) | tuple[0]; } +function toUuid(tuple: bigint[]) { + const num = uint128ToBigInt(tuple); + + const str = num.toString(16).padStart(32, '0'); + const parts = [ + str.slice(0, 8), + str.slice(8, 12), + str.slice(12, 16), + str.slice(16, 20), + str.slice(20), + ]; + + return parts.join('-'); +} + function mapPrimitiveValue(val: PrimitiveValue) { switch (val.value.oneofKind) { case 'stringVal': @@ -482,6 +500,7 @@ function mapValueType(typeDef: Omit): RelTypeDef { case 'Missing': case 'Hash': case 'AutoNumber': + case 'UUID': return { type: standardValueType, }; diff --git a/src/results/tests.ts b/src/results/tests.ts index 737dad7..5933b57 100644 --- a/src/results/tests.ts +++ b/src/results/tests.ts @@ -590,6 +590,20 @@ export const standardTypeTests: Test[] = [ values: [1n], displayValues: ['1'], }, + { + name: 'UUID', + query: ` + with rel:base use uuid_from_string + def output = uuid_from_string["22b4a8a1-e548-4eeb-9270-60426d66a48e"] + `, + typeDefs: [ + { + type: 'UUID', + }, + ], + values: ['22b4a8a1-e548-4eeb-9270-60426d66a48e'], + displayValues: ['"22b4a8a1-e548-4eeb-9270-60426d66a48e"'], + }, ]; export const specializationTests: Test[] = [ @@ -1406,6 +1420,25 @@ export const specializationTests: Test[] = [ values: [1n], displayValues: ['1'], }, + { + name: 'UUID', + query: ` + with rel:base use uuid_from_string + def v = uuid_from_string["22b4a8a1-e548-4eeb-9270-60426d66a48e"] + def output = #(v) + `, + typeDefs: [ + { + type: 'Constant', + value: { + type: 'UUID', + value: '22b4a8a1-e548-4eeb-9270-60426d66a48e', + }, + }, + ], + values: ['22b4a8a1-e548-4eeb-9270-60426d66a48e'], + displayValues: ['"22b4a8a1-e548-4eeb-9270-60426d66a48e"'], + }, ]; export const valueTypeTests: Test[] = [ @@ -2558,6 +2591,34 @@ export const valueTypeTests: Test[] = [ values: [[':MyType', 1n, 1n]], displayValues: ['(:MyType, 1, 1)'], }, + { + name: 'UUID', + query: ` + with rel:base use uuid_from_string, UUID + def uuid = uuid_from_string["22b4a8a1-e548-4eeb-9270-60426d66a48e"] + value type MyType = Int, UUID + def output = ^MyType[1, uuid] + `, + typeDefs: [ + { + type: 'ValueType', + typeDefs: [ + { + type: 'Constant', + value: { type: 'String', value: ':MyType' }, + }, + { + type: 'Int64', + }, + { + type: 'UUID', + }, + ], + }, + ], + values: [[':MyType', 1n, '22b4a8a1-e548-4eeb-9270-60426d66a48e']], + displayValues: ['(:MyType, 1, "22b4a8a1-e548-4eeb-9270-60426d66a48e")'], + }, ]; export const miscValueTypeTests: Test[] = [ @@ -4106,4 +4167,37 @@ export const valueTypeSpecializationTests: Test[] = [ values: [[':MyType', 1n, 1n]], displayValues: ['(:MyType, 1, 1)'], }, + { + name: 'UUID', + query: ` + with rel:base use uuid_from_string, UUID + def uuid = uuid_from_string["22b4a8a1-e548-4eeb-9270-60426d66a48e"] + value type MyType = UUID, Int + def v = ^MyType[uuid, 1] + def output = #(v) + `, + typeDefs: [ + { + type: 'Constant', + value: { + type: 'ValueType', + typeDefs: [ + { + type: 'Constant', + value: { type: 'String', value: ':MyType' }, + }, + { + type: 'UUID', + }, + { + type: 'Int64', + }, + ], + value: [':MyType', '22b4a8a1-e548-4eeb-9270-60426d66a48e', 1n], + }, + }, + ], + values: [[':MyType', '22b4a8a1-e548-4eeb-9270-60426d66a48e', 1n]], + displayValues: ['(:MyType, "22b4a8a1-e548-4eeb-9270-60426d66a48e", 1)'], + }, ]; diff --git a/src/results/types.ts b/src/results/types.ts index 4b350a3..66456b0 100644 --- a/src/results/types.ts +++ b/src/results/types.ts @@ -60,7 +60,8 @@ export type RelBaseTypedValue = | Rational32Value | Rational64Value | Rational128Value - | AutoNumber; + | AutoNumber + | UUID; export type RelTypedValue = RelBaseTypedValue | ValueTypeValue | UnknownType; @@ -106,6 +107,7 @@ export type RelTypeDef = | Omit | Omit | Omit + | Omit | ConstantValue | Omit | Omit; @@ -345,6 +347,11 @@ export type AutoNumber = { value: bigint; }; +export type UUID = { + type: 'UUID'; + value: string; +}; + // TODO: should be removed with JSON based metadata implementation? export type UnknownType = { type: 'Unknown';