@balena/odata-to-abstract-sql
Advanced tools
Comparing version 5.4.10 to 5.4.11-improve-computed-fields-3346e579e5e0b2b7b01066b3d95bd5b6e6281c63
@@ -7,2 +7,6 @@ # Change Log | ||
## 5.4.11 - 2022-05-19 | ||
* Improve support for computed fields by respecting them in more places [Pagan Gazzard] | ||
## 5.4.10 - 2022-05-19 | ||
@@ -9,0 +13,0 @@ |
import * as _ from 'lodash'; | ||
import * as memoize from 'memoizee'; | ||
import { AbstractSqlQuery, AbstractSqlModel, AbstractSqlTable, DurationNode, AbstractSqlType, SelectNode, FromNode, WhereNode, OrderByNode, LimitNode, OffsetNode, NumberTypeNodes, FieldsNode, ValuesNode, ReferencedFieldNode, BooleanTypeNodes, SelectQueryNode, BindNode, TableNode, Definition as ModernDefinition, ResourceNode, UnionQueryNode } from '@balena/abstract-sql-compiler'; | ||
import { AbstractSqlQuery, AbstractSqlModel, AbstractSqlTable, DurationNode, AbstractSqlType, SelectNode, FromNode, WhereNode, OrderByNode, LimitNode, OffsetNode, NumberTypeNodes, FieldsNode, ValuesNode, ReferencedFieldNode, AliasNode, BooleanTypeNodes, SelectQueryNode, BindNode, TableNode, Definition as ModernDefinition, ResourceNode, UnionQueryNode, FromTypeNodes } from '@balena/abstract-sql-compiler'; | ||
import type { ODataBinds, ODataQuery, SupportedMethod, ExpandPropertyPath, ResourceOptions, OrderByOption, OrderByPropertyPath, FilterOption, BindReference } from '@balena/odata-parser'; | ||
@@ -38,2 +38,3 @@ export type { ODataBinds, ODataQuery, SupportedMethod }; | ||
}, bypassDefinition?: boolean): void; | ||
compile(queryType: 'SelectQuery'): SelectQueryNode; | ||
compile(queryType: string): AbstractSqlQuery; | ||
@@ -118,3 +119,4 @@ } | ||
Synonym(sqlName: string): string; | ||
getTableReference(resource: Resource, extraBindVars: ODataBinds, bindVarsLength: number, bypassDefinition?: boolean, tableAlias?: string): FromTypeNodes | AliasNode<FromTypeNodes>; | ||
rewriteDefinition(definition: Definition, extraBindVars: ODataBinds, bindVarsLength: number): ModernDefinition; | ||
} |
@@ -65,12 +65,4 @@ "use strict"; | ||
fromResource(odataToAbstractSql, resource, args = odataToAbstractSql, bypassDefinition) { | ||
if (bypassDefinition !== true && resource.definition) { | ||
const definition = odataToAbstractSql.rewriteDefinition(resource.definition, args.extraBindVars, args.bindVarsLength); | ||
this.from.push(['Alias', definition.abstractSql, resource.tableAlias]); | ||
} | ||
else if (resource.name !== resource.tableAlias) { | ||
this.from.push(['Alias', ['Table', resource.name], resource.tableAlias]); | ||
} | ||
else { | ||
this.from.push(['Table', resource.name]); | ||
} | ||
const tableRef = odataToAbstractSql.getTableReference(resource, args.extraBindVars, args.bindVarsLength, bypassDefinition, resource.tableAlias); | ||
this.from.push(tableRef); | ||
} | ||
@@ -130,2 +122,6 @@ compile(queryType) { | ||
exports.isBindReference = isBindReference; | ||
const isDynamicResource = (resource) => { | ||
return (resource.definition != null || | ||
resource.fields.some((f) => f.computed != null)); | ||
}; | ||
const addBodyKey = (resourceName, fieldName, bind, bodyKeys, extraBodyVars) => { | ||
@@ -316,3 +312,3 @@ const qualifiedIDField = resourceName + '.' + fieldName; | ||
query.extras.push(['Fields', bindVars.map((b) => b[0])]); | ||
if ((hasQueryOpts || resource.definition || pathKeyWhere != null) && | ||
if ((hasQueryOpts || isDynamicResource(resource) || pathKeyWhere != null) && | ||
(method === 'POST' || method === 'PUT-INSERT')) { | ||
@@ -358,6 +354,15 @@ const subQuery = new Query(); | ||
let found = false; | ||
unionResource.definition.abstractSql = | ||
unionResource.definition.abstractSql.map((part) => { | ||
if ((0, abstract_sql_compiler_1.isFromNode)(part)) { | ||
if (isTable(part[1])) { | ||
const replaceInsertTableNodeWithBinds = (part) => { | ||
if ((0, abstract_sql_compiler_1.isFromNode)(part)) { | ||
if (isTable(part[1])) { | ||
found = true; | ||
return [ | ||
'From', | ||
['Alias', bindVarSelectQuery, unionResource.name], | ||
]; | ||
} | ||
else if ((0, abstract_sql_compiler_1.isAliasNode)(part[1]) && | ||
part[1][2] === unionResource.name) { | ||
const aliasedNode = part[1][1]; | ||
if (isTable(aliasedNode)) { | ||
found = true; | ||
@@ -369,9 +374,18 @@ return [ | ||
} | ||
else if ((0, abstract_sql_compiler_1.isAliasNode)(part[1]) && isTable(part[1][1])) { | ||
found = true; | ||
return ['From', ['Alias', bindVarSelectQuery, part[1][2]]]; | ||
else if (aliasedNode[0] === 'SelectQuery') { | ||
return [ | ||
'From', | ||
[ | ||
'Alias', | ||
aliasedNode.map(replaceInsertTableNodeWithBinds), | ||
unionResource.name, | ||
], | ||
]; | ||
} | ||
} | ||
return part; | ||
}); | ||
} | ||
return part; | ||
}; | ||
unionResource.definition.abstractSql = | ||
unionResource.definition.abstractSql.map(replaceInsertTableNodeWithBinds); | ||
if (!found) { | ||
@@ -408,3 +422,3 @@ throw new Error('Could not replace table entry in definition for insert'); | ||
} | ||
if ((hasQueryOpts || resource.definition) && | ||
if ((hasQueryOpts || isDynamicResource(resource)) && | ||
(method === 'PUT' || | ||
@@ -1164,2 +1178,40 @@ method === 'PATCH' || | ||
} | ||
getTableReference(resource, extraBindVars, bindVarsLength, bypassDefinition = false, tableAlias) { | ||
const maybeAlias = (tableRef) => { | ||
if (tableAlias == null) { | ||
return tableRef; | ||
} | ||
if ((0, abstract_sql_compiler_1.isTableNode)(tableRef) && tableRef[1] === tableAlias) { | ||
return tableRef; | ||
} | ||
else if ((0, abstract_sql_compiler_1.isAliasNode)(tableRef)) { | ||
if (tableRef[2] === tableAlias) { | ||
return tableRef; | ||
} | ||
return ['Alias', tableRef[1], tableAlias]; | ||
} | ||
else { | ||
return ['Alias', tableRef, tableAlias]; | ||
} | ||
}; | ||
if (bypassDefinition !== true) { | ||
if (resource.definition) { | ||
const definition = this.rewriteDefinition(resource.definition, extraBindVars, bindVarsLength); | ||
return maybeAlias(definition.abstractSql); | ||
} | ||
if (resource.fields.some((f) => f.computed != null)) { | ||
const computedFieldQuery = new Query(); | ||
computedFieldQuery.select = resource.fields.map((field) => this.AliasSelectField(resource, (0, exports.sqlNameToODataName)(field.fieldName), field.computed, field.fieldName)); | ||
computedFieldQuery.fromResource(this, { | ||
tableAlias: resource.name, | ||
...resource, | ||
}, { | ||
extraBindVars, | ||
bindVarsLength, | ||
}, true); | ||
return maybeAlias(computedFieldQuery.compile('SelectQuery')); | ||
} | ||
} | ||
return maybeAlias(['Table', resource.name]); | ||
} | ||
rewriteDefinition(definition, extraBindVars, bindVarsLength) { | ||
@@ -1174,18 +1226,4 @@ const rewrittenDefinition = _.cloneDeep(convertToModernDefinition(definition)); | ||
} | ||
if (referencedResource.definition) { | ||
const subDefinition = this.rewriteDefinition(referencedResource.definition, extraBindVars, bindVarsLength); | ||
resource.splice(0, resource.length, ...subDefinition.abstractSql); | ||
} | ||
else if (referencedResource.fields.some((field) => field.computed != null)) { | ||
const computedFieldQuery = new Query(); | ||
computedFieldQuery.select = referencedResource.fields.map((field) => this.AliasSelectField(referencedResource, (0, exports.sqlNameToODataName)(field.fieldName), field.computed, field.fieldName)); | ||
computedFieldQuery.fromResource(this, { | ||
...referencedResource, | ||
tableAlias: referencedResource.name, | ||
}); | ||
resource.splice(0, resource.length, ...computedFieldQuery.compile('SelectQuery')); | ||
} | ||
else { | ||
resource.splice(0, resource.length, ...['Table', referencedResource.name]); | ||
} | ||
const tableRef = this.getTableReference(referencedResource, extraBindVars, bindVarsLength); | ||
resource.splice(0, resource.length, ...tableRef); | ||
}); | ||
@@ -1192,0 +1230,0 @@ return rewrittenDefinition; |
{ | ||
"name": "@balena/odata-to-abstract-sql", | ||
"version": "5.4.10", | ||
"version": "5.4.11-improve-computed-fields-3346e579e5e0b2b7b01066b3d95bd5b6e6281c63", | ||
"description": "A consumer of the OData parser, written in OMeta", | ||
@@ -57,4 +57,4 @@ "main": "out/odata-to-abstract-sql.js", | ||
"versionist": { | ||
"publishedAt": "2022-05-19T18:27:30.234Z" | ||
"publishedAt": "2022-05-19T19:26:51.050Z" | ||
} | ||
} |
@@ -33,2 +33,3 @@ import * as _ from 'lodash'; | ||
UnionQueryNode, | ||
FromTypeNodes, | ||
isAliasNode, | ||
@@ -152,15 +153,13 @@ isFromNode, | ||
): void { | ||
if (bypassDefinition !== true && resource.definition) { | ||
const definition = odataToAbstractSql.rewriteDefinition( | ||
resource.definition, | ||
args.extraBindVars, | ||
args.bindVarsLength, | ||
); | ||
this.from.push(['Alias', definition.abstractSql, resource.tableAlias]); | ||
} else if (resource.name !== resource.tableAlias) { | ||
this.from.push(['Alias', ['Table', resource.name], resource.tableAlias]); | ||
} else { | ||
this.from.push(['Table', resource.name]); | ||
} | ||
const tableRef = odataToAbstractSql.getTableReference( | ||
resource, | ||
args.extraBindVars, | ||
args.bindVarsLength, | ||
bypassDefinition, | ||
resource.tableAlias, | ||
); | ||
this.from.push(tableRef); | ||
} | ||
compile(queryType: 'SelectQuery'): SelectQueryNode; | ||
compile(queryType: string): AbstractSqlQuery; | ||
compile(queryType: string): AbstractSqlQuery { | ||
@@ -245,2 +244,9 @@ const compiled: AbstractSqlType[] = []; | ||
const isDynamicResource = (resource: Resource): boolean => { | ||
return ( | ||
resource.definition != null || | ||
resource.fields.some((f) => f.computed != null) | ||
); | ||
}; | ||
const addBodyKey = ( | ||
@@ -477,3 +483,3 @@ resourceName: string, | ||
if ( | ||
(hasQueryOpts || resource.definition || pathKeyWhere != null) && | ||
(hasQueryOpts || isDynamicResource(resource) || pathKeyWhere != null) && | ||
(method === 'POST' || method === 'PUT-INSERT') | ||
@@ -530,6 +536,18 @@ ) { | ||
let found = false; | ||
unionResource.definition.abstractSql = | ||
unionResource.definition.abstractSql.map((part) => { | ||
if (isFromNode(part)) { | ||
if (isTable(part[1])) { | ||
const replaceInsertTableNodeWithBinds = ( | ||
part: SelectQueryNode[number], | ||
): SelectQueryNode[number] => { | ||
if (isFromNode(part)) { | ||
if (isTable(part[1])) { | ||
found = true; | ||
return [ | ||
'From', | ||
['Alias', bindVarSelectQuery, unionResource.name], | ||
]; | ||
} else if ( | ||
isAliasNode(part[1]) && | ||
part[1][2] === unionResource.name | ||
) { | ||
const aliasedNode = part[1][1]; | ||
if (isTable(aliasedNode)) { | ||
found = true; | ||
@@ -540,9 +558,22 @@ return [ | ||
]; | ||
} else if (isAliasNode(part[1]) && isTable(part[1][1])) { | ||
found = true; | ||
return ['From', ['Alias', bindVarSelectQuery, part[1][2]]]; | ||
} else if (aliasedNode[0] === 'SelectQuery') { | ||
return [ | ||
'From', | ||
[ | ||
'Alias', | ||
aliasedNode.map( | ||
replaceInsertTableNodeWithBinds, | ||
) as SelectQueryNode, | ||
unionResource.name, | ||
], | ||
]; | ||
} | ||
} | ||
return part; | ||
}) as SelectQueryNode; | ||
} | ||
return part; | ||
}; | ||
unionResource.definition.abstractSql = | ||
unionResource.definition.abstractSql.map( | ||
replaceInsertTableNodeWithBinds, | ||
) as SelectQueryNode; | ||
if (!found) { | ||
@@ -585,3 +616,3 @@ throw new Error( | ||
if ( | ||
(hasQueryOpts || resource.definition) && | ||
(hasQueryOpts || isDynamicResource(resource)) && | ||
(method === 'PUT' || | ||
@@ -1487,2 +1518,65 @@ method === 'PATCH' || | ||
getTableReference( | ||
resource: Resource, | ||
extraBindVars: ODataBinds, | ||
bindVarsLength: number, | ||
bypassDefinition: boolean = false, | ||
tableAlias?: string, | ||
): FromTypeNodes | AliasNode<FromTypeNodes> { | ||
const maybeAlias = ( | ||
tableRef: FromTypeNodes | AliasNode<FromTypeNodes>, | ||
): FromTypeNodes | AliasNode<FromTypeNodes> => { | ||
if (tableAlias == null) { | ||
return tableRef; | ||
} | ||
if (isTableNode(tableRef) && tableRef[1] === tableAlias) { | ||
// Alias if the table name doesn't match the desired alias | ||
return tableRef; | ||
} else if (isAliasNode(tableRef)) { | ||
if (tableRef[2] === tableAlias) { | ||
return tableRef; | ||
} | ||
return ['Alias', tableRef[1], tableAlias]; | ||
} else { | ||
return ['Alias', tableRef, tableAlias]; | ||
} | ||
}; | ||
if (bypassDefinition !== true) { | ||
if (resource.definition) { | ||
const definition = this.rewriteDefinition( | ||
resource.definition, | ||
extraBindVars, | ||
bindVarsLength, | ||
); | ||
return maybeAlias(definition.abstractSql); | ||
} | ||
if (resource.fields.some((f) => f.computed != null)) { | ||
const computedFieldQuery = new Query(); | ||
computedFieldQuery.select = resource.fields.map((field) => | ||
this.AliasSelectField( | ||
resource, | ||
sqlNameToODataName(field.fieldName), | ||
field.computed, | ||
field.fieldName, | ||
), | ||
); | ||
computedFieldQuery.fromResource( | ||
this, | ||
{ | ||
tableAlias: resource.name, | ||
...resource, | ||
}, | ||
{ | ||
extraBindVars, | ||
bindVarsLength, | ||
}, | ||
true, | ||
); | ||
return maybeAlias(computedFieldQuery.compile('SelectQuery')); | ||
} | ||
} | ||
return maybeAlias(['Table', resource.name]); | ||
} | ||
rewriteDefinition( | ||
@@ -1506,42 +1600,8 @@ definition: Definition, | ||
} | ||
if (referencedResource.definition) { | ||
const subDefinition = this.rewriteDefinition( | ||
referencedResource.definition, | ||
extraBindVars, | ||
bindVarsLength, | ||
); | ||
(resource as AbstractSqlType[]).splice( | ||
0, | ||
resource.length, | ||
...(subDefinition.abstractSql as AbstractSqlType[]), | ||
); | ||
} else if ( | ||
referencedResource.fields.some((field) => field.computed != null) | ||
) { | ||
const computedFieldQuery = new Query(); | ||
computedFieldQuery.select = referencedResource.fields.map((field) => | ||
this.AliasSelectField( | ||
referencedResource, | ||
sqlNameToODataName(field.fieldName), | ||
field.computed, | ||
field.fieldName, | ||
), | ||
); | ||
computedFieldQuery.fromResource(this, { | ||
...referencedResource, | ||
tableAlias: referencedResource.name, | ||
}); | ||
(resource as AbstractSqlType[]).splice( | ||
0, | ||
resource.length, | ||
...computedFieldQuery.compile('SelectQuery'), | ||
); | ||
} else { | ||
resource.splice( | ||
0, | ||
resource.length, | ||
...['Table', referencedResource.name], | ||
); | ||
} | ||
const tableRef = this.getTableReference( | ||
referencedResource, | ||
extraBindVars, | ||
bindVarsLength, | ||
); | ||
(resource as AbstractSqlType[]).splice(0, resource.length, ...tableRef); | ||
}, | ||
@@ -1548,0 +1608,0 @@ ); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
441085
6080
2