Browse Source

Update query function

Add parsing for query directives.
master
TheoryOfNekomata 7 months ago
parent
commit
0397c9c12c
2 changed files with 108 additions and 74 deletions
  1. +75
    -69
      packages/core/src/backend/data-source/queries.ts
  2. +33
    -5
      packages/core/test/features/query.test.ts

+ 75
- 69
packages/core/src/backend/data-source/queries.ts View File

@@ -1,92 +1,98 @@
export const DIRECTIVE_MAP = {
'=': 'equals',
'!=': 'not-equals',
'<': 'greater-than',
'>': 'less-than',
'<=': 'greater-than-equal',
'>=': 'less-than-equal',
'>=': 'greater-than-equal',
'<=': 'less-than-equal',
'>': 'greater-than',
'<': 'less-than',
};

export const DATA_SOURCE_QUERY_OPERATORS = Object.keys(DIRECTIVE_MAP) as (keyof typeof DIRECTIVE_MAP)[];

export type DataSourceQueryOperator = typeof DATA_SOURCE_QUERY_OPERATORS[number];

export interface DataSourceQuery {
export interface DataSourceOperatorQuery {
lhs: string;
operator: DataSourceQueryOperator;
rhs: string;
}

export interface DataSourceFunctionQuery {
name: string;
args: string[];
}

export type DataSourceQuery = DataSourceOperatorQuery | DataSourceFunctionQuery;

interface ConvertToDataSourceQueryCollectionOptions {
}

const parseDirectives = (valueRaw: string) => {
let operator = '=';

let hasDirective: boolean;
let valueTest = valueRaw.toLowerCase();
let valuePredicate = valueRaw;
const fragments = valueTest.split('.');
const directiveShorthands = Object.values(DIRECTIVE_MAP).map((s) => {
// TODO how to parse?
})
do {
hasDirective = false;

if (valueTest.startsWith('.neq.')) {
operator = '!=';

valueTest = valueTest.slice('.neq.'.length);
valuePredicate = valuePredicate.slice('.neq.'.length);
hasDirective = true;
} else if (valueTest.startsWith('.gt.eq.')) {
operator = '>=';

valueTest = valueTest.slice('.gt.eq.'.length);
valuePredicate = valuePredicate.slice('.gt.eq.'.length);
hasDirective = true;
} else if (valueTest.startsWith('.gte.')) {
operator = '>=';

valueTest = valueTest.slice('.gte.'.length);
valuePredicate = valuePredicate.slice('.gte.'.length);
hasDirective = true;
} else if (valueTest.startsWith('.lt.eq.')) {
operator = '<=';

valueTest = valueTest.slice('.lt.eq.'.length);
valuePredicate = valuePredicate.slice('.lt.eq.'.length);
hasDirective = true;
} else if (valueTest.startsWith('.lte.')) {
operator = '<=';

valueTest = valueTest.slice('.lte.'.length);
valuePredicate = valuePredicate.slice('.lte.'.length);
hasDirective = true;
} else if (valueTest.startsWith('.gt.')) {
operator = '>';

valueTest = valueTest.slice('.gt.'.length);
valuePredicate = valuePredicate.slice('.gt.'.length);
hasDirective = true;
} else if (valueTest.startsWith('.lt.')) {
operator = '<';

valueTest = valueTest.slice('.lt.'.length);
valuePredicate = valuePredicate.slice('.lt.'.length);
hasDirective = true;
} else if (valueTest.startsWith('.eq.')) {
operator = '=';

valueTest = valueTest.slice('.eq.'.length);
valuePredicate = valuePredicate.slice('.eq.'.length);
hasDirective = true;
}
} while (hasDirective);
const fragments = valueRaw.split('.');

if (!(
fragments.length > 1 && fragments[0].length === 0
)) {
return {
operator: '=',
rhs: valueRaw,
};
}

const theOperator = fragments.slice(1, -1).reduce(
(theState, f) => {
const whichDirective = Object.entries(DIRECTIVE_MAP).find(
([, match]) => {
const remainingChars = match.split('').reduce(
(rem, matchChar) => {
if (matchChar === rem.charAt(0)) {
return rem.slice(1);
}

return rem;
},
f.toLowerCase()
);

return remainingChars.length <= 0;
},
);

const selectedOperator = whichDirective?.[0] ?? theState.operator;

if (selectedOperator === '=') {
if (theState.operator === '>') {
return {
...theState,
operator: '>=',
currentToken: `${theState.currentToken}${f}`,
};
}

if (theState.operator === '<') {
return {
...theState,
operator: '<=',
currentToken: `${theState.currentToken}${f}`,
};
}
}

return {
...theState,
operator: selectedOperator,
currentToken: `${theState.currentToken}${f}`,
};
},
{
operator: undefined as (string | undefined),
currentToken: '',
},
);

return {
operator,
rhs: valuePredicate,
operator: theOperator.operator ?? '=',
rhs: fragments.at(-1),
};
};



+ 33
- 5
packages/core/test/features/query.test.ts View File

@@ -78,11 +78,24 @@ describe('query', () => {
]);
});

it('returns a greater than or equal expression query', () => {
it.only('returns a greater than or equal expression query', () => {
// expect(
// convertToDataSourceQueryCollection(
// new URLSearchParams({
// attr: '.gt.eq.foo'
// })
// )
// ).toEqual([
// {
// lhs: 'attr',
// operator: '>=',
// rhs: '"foo"',
// },
// ]);
expect(
convertToDataSourceQueryCollection(
new URLSearchParams({
attr: '.gt.eq.foo'
attr: '.gte.foo'
})
)
).toEqual([
@@ -92,19 +105,34 @@ describe('query', () => {
rhs: '"foo"',
},
]);

expect(
convertToDataSourceQueryCollection(
new URLSearchParams({
attr: '.gte.foo'
attr: '.neq.test'
})
)
).toEqual([
{
lhs: 'attr',
operator: '>=',
rhs: '"foo"',
operator: '!=',
rhs: '"test"',
},
]);

// expect(
// convertToDataSourceQueryCollection(
// new URLSearchParams({
// attr: '.gte.foo..test'
// })
// )
// ).toEqual([
// {
// lhs: 'attr',
// operator: '>=',
// rhs: '"foo.test"',
// },
// ]);
});

it('returns a less than or equal expression query', () => {


Loading…
Cancel
Save