Skip to content

Commit

Permalink
Minor refactor to improve understanding of sync rules.
Browse files Browse the repository at this point in the history
  • Loading branch information
rkistner committed Jul 2, 2024
1 parent 33bbb8c commit 474bac6
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 38 deletions.
2 changes: 1 addition & 1 deletion packages/sync-rules/src/SqlDataQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ export class SqlDataQuery {
evaluateRow(table: SourceTableInterface, row: SqliteRow): EvaluationResult[] {
try {
const tables = { [this.table!]: this.addSpecialParameters(table, row) };
const bucketParameters = this.filter!.filter(tables);
const bucketParameters = this.filter!.filterRow(tables);
const bucketIds = bucketParameters.map((params) =>
getBucketId(this.descriptor_name!, this.bucket_parameters!, params)
);
Expand Down
2 changes: 1 addition & 1 deletion packages/sync-rules/src/SqlParameterQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ export class SqlParameterQuery {
[this.table!]: row
};
try {
const filterParameters = this.filter!.filter(tables);
const filterParameters = this.filter!.filterRow(tables);
let result: EvaluatedParametersResult[] = [];
for (let filterParamSet of filterParameters) {
let lookup: SqliteJsonValue[] = [this.descriptor_name!, this.id!];
Expand Down
2 changes: 1 addition & 1 deletion packages/sync-rules/src/StaticSqlParameterQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class StaticSqlParameterQuery {

getStaticBucketIds(parameters: SyncParameters): string[] {
const tables = { token_parameters: parameters.token_parameters, user_parameters: parameters.user_parameters };
const filtered = this.filter!.filter(tables);
const filtered = this.filter!.filterRow(tables);
if (filtered.length == 0) {
return [];
}
Expand Down
34 changes: 17 additions & 17 deletions packages/sync-rules/src/sql_filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,15 @@ export class SqlTools {
getType() {
return ExpressionType.INTEGER;
}
};
} satisfies StaticRowValueClause;
} else if (isStatic(expr)) {
const value = staticValue(expr);
return {
evaluate: () => value,
getType() {
return ExpressionType.fromTypeText(sqliteTypeOf(value));
}
};
} satisfies StaticRowValueClause;
} else if (expr.type == 'ref') {
const column = expr.name;
if (column == '*') {
Expand All @@ -169,7 +169,7 @@ export class SqlTools {
getType(schema) {
return schema.getType(table, column);
}
};
} satisfies StaticRowValueClause;
} else {
const ref = [(expr as ExprRef).table?.schema, (expr as ExprRef).table?.name, (expr as ExprRef).name]
.filter((e) => e != null)
Expand Down Expand Up @@ -226,7 +226,7 @@ export class SqlTools {
error: false,
bucketParameters: [otherFilter.bucketParameter],
unbounded: false,
filter(tables: QueryParameters): TrueIfParametersMatch {
filterRow(tables: QueryParameters): TrueIfParametersMatch {
const value = staticFilter.evaluate(tables);
if (value == null) {
// null never matches on =
Expand All @@ -239,7 +239,7 @@ export class SqlTools {
}
return [{ [otherFilter.bucketParameter]: value }];
}
};
} satisfies ParameterMatchClause;
} else if (isParameterMatchClause(otherFilter)) {
// 3. static, parameterMatch
// (bucket.param = 'something') = staticValue
Expand All @@ -265,7 +265,7 @@ export class SqlTools {
error: false,
bucketParameters: [param],
unbounded: true,
filter(tables: QueryParameters): TrueIfParametersMatch {
filterRow(tables: QueryParameters): TrueIfParametersMatch {
const aValue = rightFilter.evaluate(tables);
if (aValue == null) {
return MATCH_CONST_FALSE;
Expand All @@ -278,7 +278,7 @@ export class SqlTools {
return { [param]: value };
});
}
};
} satisfies ParameterMatchClause;
} else if (
this.supports_expanding_parameters &&
isStaticRowValueClause(leftFilter) &&
Expand All @@ -289,15 +289,15 @@ export class SqlTools {
error: false,
bucketParameters: [param],
unbounded: false,
filter(tables: QueryParameters): TrueIfParametersMatch {
filterRow(tables: QueryParameters): TrueIfParametersMatch {
const value = leftFilter.evaluate(tables);
if (!isJsonValue(value)) {
// Cannot persist, e.g. BLOB
return MATCH_CONST_FALSE;
}
return [{ [param]: value }];
}
};
} satisfies ParameterMatchClause;
} else {
return this.error(`Unsupported usage of IN operator`, expr);
}
Expand Down Expand Up @@ -326,7 +326,7 @@ export class SqlTools {
getType() {
return ExpressionType.INTEGER;
}
};
} satisfies StaticRowValueClause;
} else if (expr.op == 'IS NULL') {
const leftFilter = this.compileClause(expr.operand);
if (isClauseError(leftFilter)) {
Expand All @@ -338,18 +338,18 @@ export class SqlTools {
getType() {
return ExpressionType.INTEGER;
}
};
} satisfies StaticRowValueClause;
return compileStaticOperator('IS', leftFilter, nullValue);
} else if (isParameterValueClause(leftFilter)) {
// 2. param IS NULL
return {
error: false,
bucketParameters: [leftFilter.bucketParameter],
unbounded: false,
filter(tables: QueryParameters): TrueIfParametersMatch {
filterRow(tables: QueryParameters): TrueIfParametersMatch {
return [{ [leftFilter.bucketParameter]: null }];
}
};
} satisfies ParameterMatchClause;
} else {
return this.error(`Cannot use IS NULL here`, expr);
}
Expand All @@ -364,7 +364,7 @@ export class SqlTools {
getType() {
return ExpressionType.INTEGER;
}
};
} satisfies StaticRowValueClause;
return compileStaticOperator('IS NOT', leftFilter, nullValue);
} else {
return this.error(`Cannot use IS NOT NULL here`, expr);
Expand Down Expand Up @@ -405,7 +405,7 @@ export class SqlTools {
const argTypes = argExtractors.map((e) => e.getType(schema));
return fnImpl.getReturnType(argTypes);
}
};
} satisfies StaticRowValueClause;
} else if (expr.type == 'member') {
const operand = this.compileClause(expr.operand);
if (isClauseError(operand)) {
Expand All @@ -423,7 +423,7 @@ export class SqlTools {
getType() {
return ExpressionType.ANY_JSON;
}
};
} satisfies StaticRowValueClause;
} else {
return this.error(`Unsupported member operation ${expr.op}`, expr);
}
Expand All @@ -447,7 +447,7 @@ export class SqlTools {
getType() {
return ExpressionType.fromTypeText(to as SqliteType);
}
};
} satisfies StaticRowValueClause;
} else {
return this.error(`CAST not supported for '${to}'`, expr);
}
Expand Down
30 changes: 15 additions & 15 deletions packages/sync-rules/src/sql_support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ export function andFilters(a: CompiledClause, b: CompiledClause): CompiledClause
error: aFilter.error || bFilter.error,
bucketParameters: [...combined],
unbounded: aFilter.unbounded || bFilter.unbounded, // result count = a.count * b.count
filter: (tables) => {
const aResult = aFilter.filter(tables);
const bResult = bFilter.filter(tables);
filterRow: (tables) => {
const aResult = aFilter.filterRow(tables);
const bResult = bFilter.filterRow(tables);

let results: FilterParameters[] = [];
for (let result1 of aResult) {
Expand All @@ -126,7 +126,7 @@ export function andFilters(a: CompiledClause, b: CompiledClause): CompiledClause
}
return results;
}
};
} satisfies ParameterMatchClause;
}

export function orFilters(a: CompiledClause, b: CompiledClause): CompiledClause {
Expand All @@ -141,7 +141,7 @@ export function orFilters(a: CompiledClause, b: CompiledClause): CompiledClause
getType() {
return ExpressionType.INTEGER;
}
};
} satisfies StaticRowValueClause;
}

const aFilter = toBooleanParameterSetClause(a);
Expand Down Expand Up @@ -173,14 +173,14 @@ export function orParameterSetClauses(a: ParameterMatchClause, b: ParameterMatch
error: a.error || b.error,
bucketParameters: parameters,
unbounded, // result count = a.count + b.count
filter: (tables) => {
const aResult = a.filter(tables);
const bResult = b.filter(tables);
filterRow: (tables) => {
const aResult = a.filterRow(tables);
const bResult = b.filterRow(tables);

let results: FilterParameters[] = [...aResult, ...bResult];
return results;
}
};
} satisfies ParameterMatchClause;
}

/**
Expand All @@ -196,31 +196,31 @@ export function toBooleanParameterSetClause(clause: CompiledClause): ParameterMa
error: false,
bucketParameters: [],
unbounded: false,
filter(tables: QueryParameters): TrueIfParametersMatch {
filterRow(tables: QueryParameters): TrueIfParametersMatch {
const value = sqliteBool(clause.evaluate(tables));
return value ? MATCH_CONST_TRUE : MATCH_CONST_FALSE;
}
};
} satisfies ParameterMatchClause;
} else if (isClauseError(clause)) {
return {
error: true,
bucketParameters: [],
unbounded: false,
filter(tables: QueryParameters): TrueIfParametersMatch {
filterRow(tables: QueryParameters): TrueIfParametersMatch {
throw new Error('invalid clause');
}
};
} satisfies ParameterMatchClause;
} else {
// Equivalent to `bucket.param = true`
const param = clause.bucketParameter;
return {
error: false,
bucketParameters: [param],
unbounded: false,
filter(tables: QueryParameters): TrueIfParametersMatch {
filterRow(tables: QueryParameters): TrueIfParametersMatch {
return [{ [param]: SQLITE_TRUE }];
}
};
} satisfies ParameterMatchClause;
}
}

Expand Down
5 changes: 4 additions & 1 deletion packages/sync-rules/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,13 @@ export interface ParameterMatchClause {
/**
* Given a data row, give a set of filter parameters that would make the filter be true.
*
* For StaticSqlParameterQuery, the tables are token_parameters and user_parameters.
* For others, it is the table of the data or parameter query.
*
* @param tables - {table => row}
* @return The filter parameters
*/
filter(tables: QueryParameters): TrueIfParametersMatch;
filterRow(tables: QueryParameters): TrueIfParametersMatch;
}

/**
Expand Down
26 changes: 24 additions & 2 deletions packages/sync-rules/test/src/sync_rules.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ bucket_definitions:
expect(bucket.bucket_parameters).toEqual([]);
const param_query = bucket.global_parameter_queries[0];

expect(param_query.filter!.filter({ token_parameters: { is_admin: 1n } })).toEqual([{}]);
expect(param_query.filter!.filter({ token_parameters: { is_admin: 0n } })).toEqual([]);
expect(param_query.filter!.filterRow({ token_parameters: { is_admin: 1n } })).toEqual([{}]);
expect(param_query.filter!.filterRow({ token_parameters: { is_admin: 0n } })).toEqual([]);
expect(rules.getStaticBucketIds(normalizeTokenParameters({ is_admin: true }))).toEqual(['mybucket[]']);
expect(rules.getStaticBucketIds(normalizeTokenParameters({ is_admin: false }))).toEqual([]);
expect(rules.getStaticBucketIds(normalizeTokenParameters({}))).toEqual([]);
Expand Down Expand Up @@ -625,6 +625,28 @@ bucket_definitions:
]);
});

test('bucket with function on token_parameters (1)', () => {
const rules = SqlSyncRules.fromYaml(`
bucket_definitions:
mybucket:
parameters: SELECT upper(token_parameters.user_id) as upper
data: []
`);
expect(rules.errors).toEqual([]);
expect(rules.getStaticBucketIds(normalizeTokenParameters({ user_id: 'test' }))).toEqual(['mybucket["TEST"]']);
});

test.skip('bucket with function on token_parameters (2)', () => {
const rules = SqlSyncRules.fromYaml(`
bucket_definitions:
mybucket:
parameters: SELECT id from users WHERE id_upper = upper(token_parameters.user_id)
data: []
`);
expect(rules.errors).toEqual([]);
expect(rules.getStaticBucketIds(normalizeTokenParameters({ user_id: 'test' }))).toEqual(['mybucket["TEST"]']);
});

test('parameter query with token filter (1)', () => {
// Also supported: token_parameters.is_admin = true
// Not supported: token_parameters.is_admin != false
Expand Down

0 comments on commit 474bac6

Please sign in to comment.