Skip to content

Commit daa87af

Browse files
committed
feat: Support between and broader comparator derivations
1 parent 951a20b commit daa87af

File tree

3 files changed

+152
-98
lines changed

3 files changed

+152
-98
lines changed

src/features/instance/databases/DatabaseTableView.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { getDescribeTableQueryOptions } from '@/features/instance/operations/que
1616
import {
1717
getSearchByConditionsOptions,
1818
SearchCondition,
19-
translateColumnFilterToSearchCondition,
19+
translateColumnFilterToSearchConditions,
2020
} from '@/features/instance/operations/queries/getSearchByConditions';
2121
import { getSearchByIdOptions } from '@/features/instance/operations/queries/getSearchById';
2222
import { getSearchByValueOptions } from '@/features/instance/operations/queries/getSearchByValue';
@@ -75,7 +75,7 @@ export function DatabaseTableView() {
7575
for (const key in debouncedColumnFiltersValues) {
7676
if (debouncedColumnFiltersValues[key]?.length) {
7777
try {
78-
conditions.push(translateColumnFilterToSearchCondition(key, debouncedColumnFiltersValues[key], attributesMap[key]));
78+
conditions.push(...translateColumnFilterToSearchConditions(key, debouncedColumnFiltersValues[key], attributesMap[key]));
7979
}
8080
catch (err) {
8181
toast.error(String(err));

src/features/instance/operations/queries/getSearchByConditions.test.ts

Lines changed: 85 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import {
2-
parseNumericalComparator,
2+
parseComparator,
33
translateBooleanValue,
44
translateColumnFilterToSearchCondition,
5-
translateStringSearchType,
6-
translateStringSearchValue,
5+
translateColumnFilterToSearchConditions,
76
} from '@/features/instance/operations/queries/getSearchByConditions';
87
import type { InstanceAttribute } from '@/lib/api.patch';
98
import { describe, expect, it } from 'vitest';
@@ -12,64 +11,64 @@ function attr(type?: InstanceAttribute['type']): InstanceAttribute {
1211
return { attribute: 'col', type };
1312
}
1413

15-
describe('translateStringSearchType', () => {
16-
it('returns starts_with when only start anchor is present', () => {
17-
expect(translateStringSearchType(true, attr('String'))).toBe('starts_with');
18-
});
19-
20-
it('returns equals for ID type when no anchors', () => {
21-
expect(translateStringSearchType(false, attr('ID'))).toBe('equals');
22-
});
23-
24-
it('defaults to equals when no anchors and non-ID', () => {
25-
expect(translateStringSearchType(false, attr('String'))).toBe('equals');
26-
expect(translateStringSearchType(false, attr('Date'))).toBe('equals');
27-
});
28-
});
29-
30-
describe('parseNumericalComparator', () => {
14+
describe('parseComparator', () => {
3115
it('understand greater than equal', () => {
32-
expect(parseNumericalComparator('>= 10')).toEqual({
16+
expect(parseComparator('>= 10')).toEqual({
3317
comparator: 'greater_than_equal',
34-
rawNumber: '10',
18+
value: '10',
3519
});
36-
expect(parseNumericalComparator('gte 10')).toEqual({
20+
expect(parseComparator('gte 10')).toEqual({
3721
comparator: 'greater_than_equal',
38-
rawNumber: '10',
22+
value: '10',
3923
});
40-
expect(parseNumericalComparator('gte=10')).toEqual({
24+
expect(parseComparator('gte=10')).toEqual({
4125
comparator: 'greater_than_equal',
42-
rawNumber: '10',
26+
value: '10',
4327
});
4428
});
4529

4630
it('supports dates', () => {
47-
expect(parseNumericalComparator('>= 2025-10-01')).toEqual({
31+
expect(parseComparator('>= 2025-10-01')).toEqual({
4832
comparator: 'greater_than_equal',
49-
rawNumber: '2025-10-01',
33+
value: '2025-10-01',
5034
});
5135
});
5236

53-
it('throws errors with unknown operators', () => {
54-
expect(() => parseNumericalComparator('add 2')).toThrowError(
55-
'add is not a known operator; please use <, <=, >, >=, ==, or !=',
56-
);
57-
});
58-
5937
it('falls back to equals with pure numbers', () => {
60-
expect(parseNumericalComparator('2025')).toEqual({
38+
expect(parseComparator('2025')).toEqual({
6139
comparator: 'equals',
62-
rawNumber: '2025',
40+
value: '2025',
6341
});
6442
});
65-
});
6643

67-
describe('translateStringSearchValue', () => {
68-
it('strips start anchor', () => {
69-
expect(translateStringSearchValue(true, 'foo*')).toBe('foo');
44+
it('can compare strings', () => {
45+
expect(parseComparator('!= foo')).toEqual({
46+
comparator: 'ne',
47+
value: 'foo',
48+
});
49+
expect(parseComparator('=== foo')).toEqual({
50+
comparator: 'equals',
51+
value: 'foo',
52+
});
53+
expect(parseComparator('foo*')).toEqual({
54+
comparator: 'starts_with',
55+
value: 'foo',
56+
});
7057
});
71-
it('returns as-is with no anchors', () => {
72-
expect(translateStringSearchValue(false, 'foo')).toBe('foo');
58+
59+
it('can compare booleans', () => {
60+
expect(parseComparator('!= bet')).toEqual({
61+
comparator: 'ne',
62+
value: 'bet',
63+
});
64+
expect(parseComparator('=== ok')).toEqual({
65+
comparator: 'equals',
66+
value: 'ok',
67+
});
68+
expect(parseComparator('!== nope')).toEqual({
69+
comparator: 'not_equal',
70+
value: 'nope',
71+
});
7372
});
7473
});
7574

@@ -126,6 +125,21 @@ describe('translateColumnFilterToSearchCondition', () => {
126125
});
127126

128127
it('parses numeric types and comparators', () => {
128+
expect(
129+
translateColumnFilterToSearchConditions('age', '> 1 & < 10', attr('Int')),
130+
).toEqual([
131+
{
132+
search_attribute: 'age',
133+
search_type: 'greater_than',
134+
search_value: 1,
135+
},
136+
{
137+
search_attribute: 'age',
138+
search_type: 'less_than',
139+
search_value: 10,
140+
},
141+
]);
142+
129143
expect(
130144
translateColumnFilterToSearchCondition('age', '>=10', attr('Int')),
131145
).toEqual({
@@ -142,6 +156,10 @@ describe('translateColumnFilterToSearchCondition', () => {
142156
search_value: 3.14,
143157
});
144158

159+
expect(() =>
160+
translateColumnFilterToSearchCondition('score', '<= pi', attr('Float')),
161+
).toThrowError();
162+
145163
// No comparator defaults to equals
146164
expect(
147165
translateColumnFilterToSearchCondition('count', '42', attr('Int')),
@@ -168,6 +186,32 @@ describe('translateColumnFilterToSearchCondition', () => {
168186
search_type: 'equals',
169187
search_value: false,
170188
});
189+
190+
expect(
191+
translateColumnFilterToSearchCondition('active', '=== bet', attr('Boolean')),
192+
).toEqual({
193+
search_attribute: 'active',
194+
search_type: 'equals',
195+
search_value: true,
196+
});
197+
});
198+
199+
it('allows date comparisons', () => {
200+
expect(
201+
translateColumnFilterToSearchCondition('active', '>= 2025-01-10', attr('Date')),
202+
).toEqual({
203+
search_attribute: 'active',
204+
search_type: 'greater_than_equal',
205+
search_value: '2025-01-10T00:00:00.000Z',
206+
});
207+
208+
expect(
209+
translateColumnFilterToSearchCondition('active', '!= 2025-01-10', attr('Date')),
210+
).toEqual({
211+
search_attribute: 'active',
212+
search_type: 'ne',
213+
search_value: '2025-01-10T00:00:00.000Z',
214+
});
171215
});
172216

173217
it('falls back to equals for unknown or undefined attribute types', () => {

0 commit comments

Comments
 (0)