@balena/odata-to-abstract-sql
Advanced tools
Comparing version 7.0.2-build-fix-order-by-null-values-dad17da0cdc9f1ae0810f9b3f87c369717c0eace-1 to 7.1.0-build-parse-in-as-eq-any-096b64f62b6debf897e29ab873586821e3ecd5c3-1
import memoize from 'memoizee'; | ||
import type { AbstractSqlQuery, AbstractSqlModel, AbstractSqlTable, DurationNode, SelectNode, FromNode, WhereNode, OrderByNode, LimitNode, OffsetNode, NumberTypeNodes, FieldsNode, ValuesNode, ReferencedFieldNode, AliasNode, BooleanTypeNodes, SelectQueryNode, BindNode, TableNode, Definition as ModernDefinition, ResourceNode, UnionQueryNode, FromTypeNodes, FieldNode, CountNode, AddNode, InsertQueryNode, DeleteQueryNode, UpdateQueryNode, DurationTypeNodes, SubtractNode, MultiplyNode, DivideNode, NullNode, TextTypeNodes, AnyTypeNodes, StrictDateTypeNodes, JoinTypeNodes } from '@balena/abstract-sql-compiler'; | ||
import type { ODataBinds, ODataQuery, SupportedMethod, ExpandPropertyPath, ResourceOptions, OrderByOption, OrderByPropertyPath, FilterOption, BindReference, GenericPropertyPath, PropertyPath } from '@balena/odata-parser'; | ||
import type { AbstractSqlQuery, AbstractSqlModel, AbstractSqlTable, DurationNode, SelectNode, FromNode, WhereNode, OrderByNode, LimitNode, OffsetNode, NumberTypeNodes, FieldsNode, ValuesNode, ReferencedFieldNode, AliasNode, BooleanTypeNodes, SelectQueryNode, BindNode, TableNode, Definition as ModernDefinition, ResourceNode, UnionQueryNode, FromTypeNodes, FieldNode, CountNode, AddNode, InsertQueryNode, DeleteQueryNode, UpdateQueryNode, DurationTypeNodes, SubtractNode, MultiplyNode, DivideNode, NullNode, TextTypeNodes, AnyTypeNodes, StrictDateTypeNodes } from '@balena/abstract-sql-compiler'; | ||
import type { ODataBinds, ODataQuery, SupportedMethod, ExpandPropertyPath, ResourceOptions, OrderByOption, OrderByPropertyPath, FilterOption, BindReference } from '@balena/odata-parser'; | ||
export type { ODataBinds, ODataQuery, SupportedMethod }; | ||
type InternalSupportedMethod = Exclude<SupportedMethod, 'MERGE'> | 'PUT-INSERT'; | ||
type JoinType = 'Join' | 'LeftJoin' | 'RightJoin'; | ||
type RequiredAbstractSqlModelSubset = Pick<AbstractSqlModel, 'synonyms' | 'relationships' | 'tables'>; | ||
@@ -39,3 +38,2 @@ type Dictionary<T> = Record<string, T>; | ||
where: Array<WhereNode[1]>; | ||
joins: JoinTypeNodes[]; | ||
extras: Array<FieldsNode | ValuesNode | OrderByNode | LimitNode | OffsetNode>; | ||
@@ -47,6 +45,2 @@ merge(otherQuery: Query): void; | ||
}, bypassDefinition?: boolean, isModifyOperation?: boolean): void; | ||
joinResource(odataToAbstractSql: OData2AbstractSQL, resource: AliasedResource, type: JoinType, condition: BooleanTypeNodes, args?: { | ||
extraBindVars: ODataBinds; | ||
bindVarsLength: number; | ||
}, bypassDefinition?: boolean): void; | ||
addNestedFieldSelect(fieldName: string, fieldNameAlias: string): void; | ||
@@ -135,4 +129,2 @@ compile(queryType: 'SelectQuery'): SelectQueryNode; | ||
AddNavigation(query: Query, resource: Resource, extraResource: string): AliasedResource; | ||
AddJoins(query: Query, parentResource: Resource, match: GenericPropertyPath<PropertyPath> | Array<GenericPropertyPath<PropertyPath>>, joinType: JoinType): void; | ||
AddJoinNavigation(query: Query, resource: Resource, extraResource: string, joinType: JoinType): AliasedResource; | ||
reset(): void; | ||
@@ -139,0 +131,0 @@ putReset(): void; |
@@ -22,2 +22,3 @@ "use strict"; | ||
eq: 'IsNotDistinctFrom', | ||
eqany: 'EqualsAny', | ||
ne: 'IsDistinctFrom', | ||
@@ -94,3 +95,2 @@ gt: 'GreaterThan', | ||
where = []; | ||
joins = []; | ||
extras = []; | ||
@@ -101,3 +101,2 @@ merge(otherQuery) { | ||
this.where = this.where.concat(otherQuery.where); | ||
this.joins = this.joins.concat(otherQuery.joins); | ||
this.extras = this.extras.concat(otherQuery.extras); | ||
@@ -109,7 +108,2 @@ } | ||
} | ||
joinResource(odataToAbstractSql, resource, type, condition, args = odataToAbstractSql, bypassDefinition) { | ||
const tableRef = odataToAbstractSql.getTableReference(resource, args.extraBindVars, args.bindVarsLength, bypassDefinition, resource.tableAlias, undefined); | ||
const joinNode = [type, tableRef, ['On', condition]]; | ||
this.joins.push(joinNode); | ||
} | ||
addNestedFieldSelect(fieldName, fieldNameAlias) { | ||
@@ -130,5 +124,2 @@ if (this.from.length !== 1) { | ||
}); | ||
this.joins.forEach((joinNode) => { | ||
compiled.push(joinNode); | ||
}); | ||
if (where.length > 0) { | ||
@@ -578,3 +569,3 @@ if (where.length > 1) { | ||
OrderBy(orderby, query, resource) { | ||
this.AddJoins(query, resource, orderby.properties, 'LeftJoin'); | ||
this.AddExtraFroms(query, resource, orderby.properties); | ||
query.extras.push([ | ||
@@ -776,2 +767,3 @@ 'OrderBy', | ||
case 'eq': | ||
case 'eqany': | ||
case 'ne': | ||
@@ -1242,36 +1234,2 @@ case 'gt': | ||
} | ||
AddJoins(query, parentResource, match, joinType) { | ||
if (Array.isArray(match)) { | ||
match.forEach((v) => { | ||
this.AddJoins(query, parentResource, v, joinType); | ||
}); | ||
} | ||
else { | ||
let nextProp = match; | ||
let prop; | ||
while ((prop = nextProp) && | ||
prop.name && | ||
prop.property?.name) { | ||
nextProp = prop.property; | ||
const resourceAlias = this.resourceAliases[prop.name]; | ||
if (resourceAlias) { | ||
parentResource = resourceAlias; | ||
} | ||
else { | ||
parentResource = this.AddJoinNavigation(query, parentResource, prop.name, joinType); | ||
} | ||
} | ||
} | ||
} | ||
AddJoinNavigation(query, resource, extraResource, joinType) { | ||
const navigation = this.NavigateResources(resource, extraResource); | ||
if (!query.from.some((from) => ((0, abstract_sql_compiler_1.isTableNode)(from) && from[1] === navigation.resource.tableAlias) || | ||
((0, abstract_sql_compiler_1.isAliasNode)(from) && from[2] === navigation.resource.tableAlias))) { | ||
query.joinResource(this, navigation.resource, joinType, navigation.where); | ||
return navigation.resource; | ||
} | ||
else { | ||
throw new SyntaxError(`Could not navigate resources '${resource.name}' and '${extraResource}'`); | ||
} | ||
} | ||
reset() { | ||
@@ -1278,0 +1236,0 @@ this.putReset(); |
{ | ||
"name": "@balena/odata-to-abstract-sql", | ||
"version": "7.0.2-build-fix-order-by-null-values-dad17da0cdc9f1ae0810f9b3f87c369717c0eace-1", | ||
"version": "7.1.0-build-parse-in-as-eq-any-096b64f62b6debf897e29ab873586821e3ecd5c3-1", | ||
"description": "A consumer of the OData parser, written in OMeta", | ||
@@ -19,4 +19,4 @@ "type": "commonjs", | ||
"dependencies": { | ||
"@balena/abstract-sql-compiler": "^10.0.1", | ||
"@balena/odata-parser": "^3.1.0", | ||
"@balena/abstract-sql-compiler": "^10.2.0", | ||
"@balena/odata-parser": "^4.1.0", | ||
"@types/lodash": "^4.17.10", | ||
@@ -58,4 +58,4 @@ "@types/memoizee": "^0.4.11", | ||
"versionist": { | ||
"publishedAt": "2025-02-10T09:05:55.863Z" | ||
"publishedAt": "2025-02-11T14:16:43.604Z" | ||
} | ||
} |
@@ -75,3 +75,3 @@ import _ from 'lodash'; | ||
FromTypeNode, | ||
JoinTypeNodes, | ||
EqualsAnyNode, | ||
} from '@balena/abstract-sql-compiler'; | ||
@@ -88,4 +88,2 @@ import type { | ||
BindReference, | ||
GenericPropertyPath, | ||
PropertyPath, | ||
} from '@balena/odata-parser'; | ||
@@ -96,4 +94,2 @@ export type { ODataBinds, ODataQuery, SupportedMethod }; | ||
type JoinType = 'Join' | 'LeftJoin' | 'RightJoin'; | ||
type RequiredAbstractSqlModelSubset = Pick< | ||
@@ -147,2 +143,3 @@ AbstractSqlModel, | ||
eq: 'IsNotDistinctFrom', | ||
eqany: 'EqualsAny', | ||
ne: 'IsDistinctFrom', | ||
@@ -248,3 +245,2 @@ gt: 'GreaterThan', | ||
public where: Array<WhereNode[1]> = []; | ||
public joins: JoinTypeNodes[] = []; | ||
public extras: Array< | ||
@@ -258,3 +254,2 @@ FieldsNode | ValuesNode | OrderByNode | LimitNode | OffsetNode | ||
this.where = this.where.concat(otherQuery.where); | ||
this.joins = this.joins.concat(otherQuery.joins); | ||
this.extras = this.extras.concat(otherQuery.extras); | ||
@@ -282,24 +277,2 @@ } | ||
} | ||
joinResource( | ||
odataToAbstractSql: OData2AbstractSQL, | ||
resource: AliasedResource, | ||
type: JoinType, | ||
condition: BooleanTypeNodes, | ||
args: { | ||
extraBindVars: ODataBinds; | ||
bindVarsLength: number; | ||
} = odataToAbstractSql, | ||
bypassDefinition?: boolean, | ||
): void { | ||
const tableRef = odataToAbstractSql.getTableReference( | ||
resource, | ||
args.extraBindVars, | ||
args.bindVarsLength, | ||
bypassDefinition, | ||
resource.tableAlias, | ||
undefined, | ||
); | ||
const joinNode: JoinTypeNodes = [type, tableRef, ['On', condition]]; | ||
this.joins.push(joinNode); | ||
} | ||
addNestedFieldSelect(fieldName: string, fieldNameAlias: string): void { | ||
@@ -328,5 +301,2 @@ if (this.from.length !== 1) { | ||
}); | ||
this.joins.forEach((joinNode) => { | ||
compiled.push(joinNode); | ||
}); | ||
if (where.length > 0) { | ||
@@ -344,19 +314,2 @@ if (where.length > 1) { | ||
} | ||
// addJoin( | ||
// odataToAbstractSql: OData2AbstractSQL, | ||
// type: JoinType, | ||
// resource: AliasedResource, | ||
// condition: BooleanTypeNodes, | ||
// ): void { | ||
// const tableRef = odataToAbstractSql.getTableReference( | ||
// resource, | ||
// odataToAbstractSql.extraBindVars, | ||
// odataToAbstractSql.bindVarsLength, | ||
// undefined, | ||
// resource.tableAlias, | ||
// undefined, | ||
// ); | ||
// const joinNode: JoinTypeNodes = [type, tableRef, ['On', condition]]; | ||
// this.joins.push(joinNode); | ||
// } | ||
} | ||
@@ -950,3 +903,3 @@ | ||
OrderBy(orderby: OrderByOption, query: Query, resource: Resource) { | ||
this.AddJoins(query, resource, orderby.properties, 'LeftJoin'); | ||
this.AddExtraFroms(query, resource, orderby.properties); | ||
query.extras.push([ | ||
@@ -1204,2 +1157,3 @@ 'OrderBy', | ||
case 'eq': | ||
case 'eqany': | ||
case 'ne': | ||
@@ -1218,3 +1172,4 @@ case 'gt': | ||
| LessThanNode | ||
| LessThanOrEqualNode; | ||
| LessThanOrEqualNode | ||
| EqualsAnyNode; | ||
} | ||
@@ -1786,63 +1741,2 @@ case 'and': | ||
} | ||
AddJoins( | ||
query: Query, | ||
parentResource: Resource, | ||
match: | ||
| GenericPropertyPath<PropertyPath> | ||
| Array<GenericPropertyPath<PropertyPath>>, | ||
joinType: JoinType, | ||
) { | ||
if (Array.isArray(match)) { | ||
match.forEach((v) => { | ||
this.AddJoins(query, parentResource, v, joinType); | ||
}); | ||
} else { | ||
let nextProp = match; | ||
let prop; | ||
while ( | ||
// tslint:disable-next-line:no-conditional-assignment | ||
(prop = nextProp) && | ||
prop.name && | ||
prop.property?.name | ||
) { | ||
nextProp = prop.property; | ||
const resourceAlias = this.resourceAliases[prop.name]; | ||
if (resourceAlias) { | ||
parentResource = resourceAlias; | ||
} else { | ||
parentResource = this.AddJoinNavigation( | ||
query, | ||
parentResource, | ||
prop.name, | ||
joinType, | ||
); | ||
} | ||
} | ||
// if (nextProp?.args) { | ||
// this.AddJoins(query, parentResource, prop.args); | ||
// } | ||
} | ||
} | ||
AddJoinNavigation( | ||
query: Query, | ||
resource: Resource, | ||
extraResource: string, | ||
joinType: JoinType, | ||
): AliasedResource { | ||
const navigation = this.NavigateResources(resource, extraResource); | ||
if ( | ||
!query.from.some( | ||
(from) => | ||
(isTableNode(from) && from[1] === navigation.resource.tableAlias) || | ||
(isAliasNode(from) && from[2] === navigation.resource.tableAlias), | ||
) | ||
) { | ||
query.joinResource(this, navigation.resource, joinType, navigation.where); | ||
return navigation.resource; | ||
} else { | ||
throw new SyntaxError( | ||
`Could not navigate resources '${resource.name}' and '${extraResource}'`, | ||
); | ||
} | ||
} | ||
@@ -1849,0 +1743,0 @@ reset() { |
@@ -16,6 +16,2 @@ // tslint:disable-next-line:no-namespace | ||
) => Assertion; | ||
leftJoin: ( | ||
join: [string | string[], any[]], | ||
...joins: Array<[string | string[], any[]]> | ||
) => Assertion; | ||
where: (clause: any[]) => Assertion; | ||
@@ -22,0 +18,0 @@ orderby: (...clause: any[]) => Assertion; |
@@ -43,13 +43,2 @@ import _ from 'lodash'; | ||
}; | ||
const binaryClause = (bodyType) => | ||
function (...bodyClauses) { | ||
const obj = utils.flag(this, 'object'); | ||
for (let i = 0; i < bodyClauses.length; i++) { | ||
expect(obj).to.contain.something.that.deep.equals( | ||
[bodyType, bodyClauses[i][0], bodyClauses[i][1]], | ||
bodyType + ' - ' + i, | ||
); | ||
} | ||
return this; | ||
}; | ||
@@ -84,11 +73,2 @@ const select = (function () { | ||
}); | ||
const leftJoinClause = binaryClause('LeftJoin'); | ||
utils.addMethod(assertionPrototype, 'leftJoin', function (...bodyClauses) { | ||
bodyClauses = bodyClauses.map(function ([v, condition]) { | ||
const resource = | ||
typeof v === 'string' ? ['Table', v] : ['Alias', ['Table', v[0]], v[1]]; | ||
return [resource, ['On', condition]]; | ||
}); | ||
return leftJoinClause.apply(this, bodyClauses); | ||
}); | ||
utils.addMethod(assertionPrototype, 'where', bodyClause('Where')); | ||
@@ -95,0 +75,0 @@ utils.addMethod(assertionPrototype, 'orderby', function (...bodyClauses) { |
@@ -53,2 +53,3 @@ import { expect } from 'chai'; | ||
in: 'In', | ||
eqany: 'EqualsAny', | ||
}; | ||
@@ -77,5 +78,3 @@ | ||
odata: operandToOData(lhs) + ' ' + op + ' ' + operandToOData(rhs), | ||
abstractsql: [sqlOps[op], operandToAbstractSQL(lhs)].concat( | ||
operandToAbstractSQL(rhs), | ||
), | ||
abstractsql: [sqlOps['eqany'], operandToAbstractSQL(lhs), ['Bind', 0]], | ||
}; | ||
@@ -82,0 +81,0 @@ } |
@@ -53,42 +53,36 @@ import { expect } from 'chai'; | ||
test('/pilot?$orderby=licence/id asc', (result) => | ||
it('should order by licence/id asc', () => { | ||
it('should order by licence/id asc', () => | ||
expect(result) | ||
.to.be.a.query.that.selects(pilotFields) | ||
.from('pilot') | ||
.leftJoin([ | ||
['licence', 'pilot.licence'], | ||
[ | ||
'Equals', | ||
['ReferencedField', 'pilot', 'licence'], | ||
['ReferencedField', 'pilot.licence', 'id'], | ||
], | ||
.from('pilot', ['licence', 'pilot.licence']) | ||
.where([ | ||
'Equals', | ||
['ReferencedField', 'pilot', 'licence'], | ||
['ReferencedField', 'pilot.licence', 'id'], | ||
]) | ||
.orderby(['ASC', operandToAbstractSQL('licence/id')]); | ||
})); | ||
.orderby(['ASC', operandToAbstractSQL('licence/id')]))); | ||
test('/pilot?$orderby=can_fly__plane/plane/id asc', (result) => | ||
it('should order by can_fly__plane/plane/id asc', () => { | ||
it('should order by can_fly__plane/plane/id asc', () => | ||
expect(result) | ||
.to.be.a.query.that.selects(pilotFields) | ||
.from('pilot') | ||
.leftJoin( | ||
.from( | ||
'pilot', | ||
['pilot-can fly-plane', 'pilot.pilot-can fly-plane'], | ||
['plane', 'pilot.pilot-can fly-plane.plane'], | ||
) | ||
.where([ | ||
'And', | ||
[ | ||
['pilot-can fly-plane', 'pilot.pilot-can fly-plane'], | ||
[ | ||
'Equals', | ||
['ReferencedField', 'pilot', 'id'], | ||
['ReferencedField', 'pilot.pilot-can fly-plane', 'pilot'], | ||
], | ||
'Equals', | ||
['ReferencedField', 'pilot', 'id'], | ||
['ReferencedField', 'pilot.pilot-can fly-plane', 'pilot'], | ||
], | ||
[ | ||
['plane', 'pilot.pilot-can fly-plane.plane'], | ||
[ | ||
'Equals', | ||
['ReferencedField', 'pilot.pilot-can fly-plane', 'can fly-plane'], | ||
['ReferencedField', 'pilot.pilot-can fly-plane.plane', 'id'], | ||
], | ||
'Equals', | ||
['ReferencedField', 'pilot.pilot-can fly-plane', 'can fly-plane'], | ||
['ReferencedField', 'pilot.pilot-can fly-plane.plane', 'id'], | ||
], | ||
) | ||
.orderby(['ASC', operandToAbstractSQL('can_fly__plane/plane/id')]); | ||
})); | ||
]) | ||
.orderby(['ASC', operandToAbstractSQL('can_fly__plane/plane/id')]))); | ||
@@ -95,0 +89,0 @@ test.skip('/pilot?$orderby=favourite_colour/red', () => |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
1024926
7116
+ Added@balena/odata-parser@4.1.0(transitive)
- Removed@balena/odata-parser@3.1.2(transitive)
Updated@balena/odata-parser@^4.1.0