in packages/sqrl-redis-functions/src/CountUniqueFunctions.ts [201:335]
function countUnique(state: CompileState, ast: CustomCallAst): Ast {
const args: CountUniqueArguments = parse(ast.source, {
startRule: "CountUniqueArguments",
});
const { whereAst, whereFeatures, whereTruth } = state.combineGlobalWhere(
args.where
);
const sortedUniques: AliasedFeature[] = sortByAlias(args.uniques);
const sortedGroup: AliasedFeature[] = sortByAlias(args.groups);
const uniquesAst = AstBuilder.list(sortedUniques.map((f) => f.feature));
const windowMsAst = AstBuilder.constant(args.windowMs);
const groupAliases = args.groups.map((feature) => feature.alias);
const groupFeatures = args.groups.map((feature) => feature.feature.value);
const groupHasAliases = args.groups.some(
(f) => f.feature.value !== f.alias
);
const sortedGroupAliases = sortedGroup.map((feature) => feature.alias);
const { entityId, entityAst } = state.addHashedEntity(
ast,
"UniqueCounter",
{
groups: sortedGroupAliases,
uniques: sortedUniques.map((feature) => feature.alias),
// Only include the where clauses if they're non-empty
...(whereTruth ? { whereFeatures, whereTruth } : {}),
}
);
const originalKeysAst = state.setGlobal(
ast,
AstBuilder.call("_getKeyList", [
entityAst,
...groupAliases.map((alias) => AstBuilder.feature(alias)),
]),
`key(${entityId.getIdString()})`
);
// Always bump the counter according to the original keys (aliases)
const slotAst = state.setGlobal(
ast,
AstBuilder.call("_bumpCountUnique", [
AstBuilder.branch(
whereAst,
originalKeysAst,
AstBuilder.constant(null)
),
uniquesAst,
windowMsAst,
])
);
state.addStatement("SqrlCountUniqueStatements", slotAst);
let keysAst = originalKeysAst;
let countExtraUniques: Ast = AstBuilder.branch(
AstBuilder.and([whereAst, AstBuilder.feature("SqrlIsClassify")]),
uniquesAst,
AstBuilder.constant([])
);
if (groupHasAliases) {
keysAst = state.setGlobal(
ast,
AstBuilder.call("_getKeyList", [
entityAst,
...groupFeatures.map((feature) => AstBuilder.feature(feature)),
]),
`key(${entityId.getIdString()}:${groupFeatures.join(",")})`
);
// If we're using aliases we only count the uniques in this request if
// they exactly match the aliases that we used
const aliasesEqualAst = AstBuilder.call("_cmpE", [
AstBuilder.list(
groupAliases.map((alias) => AstBuilder.feature(alias))
),
AstBuilder.list(
groupFeatures.map((feature) => AstBuilder.feature(feature))
),
]);
countExtraUniques = AstBuilder.branch(
aliasesEqualAst,
countExtraUniques,
AstBuilder.constant([])
);
}
if (args.beforeAction) {
countExtraUniques = AstBuilder.constant([]);
}
const originalCall = AstBuilder.call("_fetchCountUnique", [
keysAst,
windowMsAst,
countExtraUniques,
]);
if (args.setOperation) {
throw new Error("@todo setOperation transform");
/*
const { operation, features } = args.setOperation;
const rightCountArgs = Object.assign({}, args, {
groups: features,
setOperation: null
});
const rightCall = state._wrapped.transform(
Object.assign({}, ast, {
args: [rightCountArgs, ...ast.args.slice(1)]
})
);
let setFunction;
if (operation === "intersect") {
setFunction = "_intersectCountUnique";
} else if (operation === "union") {
setFunction = "_unionCountUnique";
} else {
throw new Error("Unknown set operation: " + operation);
}
return AstBuilder.call(setFunction, [
Object.assign({}, originalCall, {
func: "_fetchCountUniqueElements"
}),
Object.assign({}, rightCall, { func: "_fetchCountUniqueElements" })
]);*/
}
return originalCall;
},