-
Notifications
You must be signed in to change notification settings - Fork 237
Export and document subtract, multiply, divide math functions #1151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
4903693
4874663
287a1ff
469c859
6b37040
6b601e5
de753a8
771e02e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| --- | ||
| '@tanstack/db': patch | ||
| --- | ||
|
|
||
| Add `subtract`, `multiply`, and `divide` math functions for computed columns | ||
|
|
||
| These functions enable complex calculations in `select` and `orderBy` clauses, such as ranking algorithms that combine multiple factors (e.g., HN-style scoring that balances recency and rating). | ||
|
|
||
| ```ts | ||
| import { subtract, multiply, divide } from '@tanstack/db' | ||
|
|
||
| // Example: Sort by computed ranking score | ||
| const ranked = createLiveQueryCollection((q) => | ||
| q | ||
| .from({ r: recipesCollection }) | ||
| .orderBy( | ||
| ({ r }) => | ||
| subtract(multiply(r.rating, r.timesMade), divide(r.ageInMs, 86400000)), | ||
| 'desc', | ||
| ), | ||
| ) | ||
| ``` | ||
|
|
||
| - `subtract(a, b)` - Subtraction | ||
| - `multiply(a, b)` - Multiplication | ||
| - `divide(a, b)` - Division (returns `null` on divide-by-zero) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -125,31 +125,12 @@ type MapToNumber<T> = T extends string | Array<any> | |
| ? null | ||
| : T | ||
|
|
||
| // Helper type for binary numeric operations (combines nullability of both operands) | ||
| type BinaryNumericReturnType<T1, T2> = | ||
| ExtractType<T1> extends infer U1 | ||
| ? ExtractType<T2> extends infer U2 | ||
| ? U1 extends number | ||
| ? U2 extends number | ||
| ? BasicExpression<number> | ||
| : U2 extends number | undefined | ||
| ? BasicExpression<number | undefined> | ||
| : U2 extends number | null | ||
| ? BasicExpression<number | null> | ||
| : BasicExpression<number | undefined | null> | ||
| : U1 extends number | undefined | ||
| ? U2 extends number | ||
| ? BasicExpression<number | undefined> | ||
| : U2 extends number | undefined | ||
| ? BasicExpression<number | undefined> | ||
| : BasicExpression<number | undefined | null> | ||
| : U1 extends number | null | ||
| ? U2 extends number | ||
| ? BasicExpression<number | null> | ||
| : BasicExpression<number | undefined | null> | ||
| : BasicExpression<number | undefined | null> | ||
| : BasicExpression<number | undefined | null> | ||
| : BasicExpression<number | undefined | null> | ||
| // Helper type for binary numeric operations. | ||
| // Runtime coalesces nullish operands to 0 for these operations, so nullable | ||
| // operands don't make the result nullable. | ||
| type BinaryNumericReturnType = BasicExpression<number> | ||
|
|
||
| type DivideReturnType = BasicExpression<number | null> | ||
|
Comment on lines
+128
to
+133
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Verify the runtime evaluator coalesces null/undefined to 0 for add/subtract/multiply
rg -nP --type=ts -C10 'add|subtract|multiply|divide' packages/db/src/query/compiler/evaluators.ts | head -100Repository: TanStack/db Length of output: 1382 Clarify PR objectives regarding nullability propagation. The code comment and type definitions are correct—the runtime does coalesce null/undefined operands to 0 for add, subtract, and multiply operations using the nullish coalescing operator ( 🤖 Prompt for AI Agents |
||
|
|
||
| // Operators | ||
|
|
||
|
|
@@ -620,11 +601,41 @@ export function caseWhen(...args: Array<CaseWhenValue>): any { | |
| export function add<T1 extends ExpressionLike, T2 extends ExpressionLike>( | ||
| left: T1, | ||
| right: T2, | ||
| ): BinaryNumericReturnType<T1, T2> { | ||
| ): BinaryNumericReturnType { | ||
| return new Func(`add`, [ | ||
| toExpression(left), | ||
| toExpression(right), | ||
| ]) as BinaryNumericReturnType<T1, T2> | ||
| ]) as BinaryNumericReturnType | ||
| } | ||
|
|
||
| export function subtract<T1 extends ExpressionLike, T2 extends ExpressionLike>( | ||
| left: T1, | ||
| right: T2, | ||
| ): BinaryNumericReturnType { | ||
| return new Func(`subtract`, [ | ||
| toExpression(left), | ||
| toExpression(right), | ||
| ]) as BinaryNumericReturnType | ||
| } | ||
|
|
||
| export function multiply<T1 extends ExpressionLike, T2 extends ExpressionLike>( | ||
| left: T1, | ||
| right: T2, | ||
| ): BinaryNumericReturnType { | ||
| return new Func(`multiply`, [ | ||
| toExpression(left), | ||
| toExpression(right), | ||
| ]) as BinaryNumericReturnType | ||
| } | ||
|
|
||
| export function divide<T1 extends ExpressionLike, T2 extends ExpressionLike>( | ||
| left: T1, | ||
| right: T2, | ||
| ): DivideReturnType { | ||
| return new Func(`divide`, [ | ||
| toExpression(left), | ||
| toExpression(right), | ||
| ]) as DivideReturnType | ||
| } | ||
|
|
||
| // Aggregates | ||
|
|
@@ -690,6 +701,9 @@ export const operators = [ | |
| `concat`, | ||
| // Numeric functions | ||
| `add`, | ||
| `subtract`, | ||
| `multiply`, | ||
| `divide`, | ||
| // Utility functions | ||
| `coalesce`, | ||
| `caseWhen`, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,6 +59,9 @@ export { | |
| coalesce, | ||
| caseWhen, | ||
| add, | ||
| subtract, | ||
| multiply, | ||
| divide, | ||
| // Aggregates | ||
| count, | ||
| avg, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.