Add explicit CRDT edit contracts and structured query values
This commit is contained in:
@@ -154,8 +154,19 @@ export function relationalCompiler(
|
||||
): QueryExpression => {
|
||||
requireAvailable(names, available, node);
|
||||
const meta = names.at(-2) === "_qx";
|
||||
const { row, path, nullable } = walk(root, names.slice(0, meta ? -2 : -1), uses, node);
|
||||
const name = names.at(-1)!;
|
||||
let fieldIndex = names.length - 1;
|
||||
if (!meta) {
|
||||
let cursor = root;
|
||||
for (let index = 0; index < names.length; index++) {
|
||||
if (cursor.kind === "object" && rowFields(cursor).get(names[index]!)?.kind === "leaf") {
|
||||
fieldIndex = index;
|
||||
break;
|
||||
}
|
||||
if (index < names.length - 1) cursor = walk(root, names.slice(0, index + 1), uses, node).row;
|
||||
}
|
||||
}
|
||||
const { row, path, nullable } = walk(root, names.slice(0, meta ? -2 : fieldIndex), uses, node);
|
||||
const name = names[meta ? names.length - 1 : fieldIndex]!;
|
||||
let type: ValueType, leaf: QueryExpression["leaf"];
|
||||
if (meta) {
|
||||
if (name === "ref" && row.kind === "object") {
|
||||
@@ -185,7 +196,24 @@ export function relationalCompiler(
|
||||
for (const use of uses) mark(row.interfaceRevisionId, name, use, node);
|
||||
const member = env.contracts.get(row.interfaceRevisionId)!.members.find((m) => m.displayName === name)!;
|
||||
type = field.type;
|
||||
leaf = { kind: "field", interfaceRevisionId: row.interfaceRevisionId, memberId: member.id };
|
||||
const valuePath = names.slice(fieldIndex + 1);
|
||||
let valueNullable = false;
|
||||
for (const component of valuePath) {
|
||||
if (type.kind === "optional") {
|
||||
valueNullable = true;
|
||||
type = type.value;
|
||||
}
|
||||
if (type.kind !== "record" || !Object.hasOwn(type.fields, component))
|
||||
return fail("QUERY_FIELD_NOT_QUERYABLE", `Unknown scalar value path ${names.join(".")}`, node);
|
||||
type = type.fields[component]!;
|
||||
}
|
||||
if (valueNullable && type.kind !== "optional") type = valueType.optional(type);
|
||||
leaf = {
|
||||
kind: "field",
|
||||
interfaceRevisionId: row.interfaceRevisionId,
|
||||
memberId: member.id,
|
||||
...(valuePath.length ? { valuePath } : {}),
|
||||
};
|
||||
}
|
||||
return { path, leaf, type: nullable && type.kind !== "optional" ? valueType.optional(type) : type };
|
||||
};
|
||||
@@ -356,15 +384,22 @@ export function relationalCompiler(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const expr = expression(row, [...base, name], ["predicate"], field, available);
|
||||
children.push(
|
||||
...(comparisons(field.value, (operator, value) => ({
|
||||
kind: "compare",
|
||||
expression: expr,
|
||||
operator,
|
||||
value,
|
||||
})) as QueryPredicate[]),
|
||||
);
|
||||
const valuePredicate = (names: string[], value: ValueNode) => {
|
||||
const expr = expression(row, names, ["predicate"], field, available);
|
||||
const type = expr.type.kind === "optional" ? expr.type.value : expr.type;
|
||||
if (type.kind === "record") {
|
||||
for (const child of pairs(value)) valuePredicate([...names, child.name.value], child.value);
|
||||
} else
|
||||
children.push(
|
||||
...(comparisons(value, (operator, value) => ({
|
||||
kind: "compare",
|
||||
expression: expr,
|
||||
operator,
|
||||
value,
|
||||
})) as QueryPredicate[]),
|
||||
);
|
||||
};
|
||||
valuePredicate([...base, name], field.value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user