Skip to content

Commit

Permalink
Optimize Duplications of ComputedField queries
Browse files Browse the repository at this point in the history
For each modelName the a `ComputedField` is only compiled into abstract-sql-query once. Aftewards it's used as ReferencedField

Change-type: minor
Signed-off-by: fisehara <[email protected]>
Signed-off-by: Harald Fischer <[email protected]>
  • Loading branch information
fisehara committed May 2, 2023
1 parent 298161f commit 870744d
Showing 1 changed file with 30 additions and 9 deletions.
39 changes: 30 additions & 9 deletions src/odata-to-abstract-sql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ type Overwrite<T, U> = Pick<T, Exclude<keyof T, keyof U>> & U;
type RequiredField<T, F extends keyof T> = Overwrite<T, Required<Pick<T, F>>>;
type AliasedResource = RequiredField<Resource, 'tableAlias'>;

type AlreadyComputedFieldsLookup = { [key: string]: boolean };

export type ResourceFunction = (
this: OData2AbstractSQL,
property: {
Expand Down Expand Up @@ -298,10 +300,17 @@ export const isBindReference = (maybeBind: {
);
};

const isDynamicResource = (resource: Resource): boolean => {
const isDynamicResource = (
resource: Resource,
alreadyComputedFieldsLookup: AlreadyComputedFieldsLookup,
): boolean => {
return (
resource.definition != null ||
resource.fields.some((f) => f.computed != null)
resource.fields.some(
(f) =>
f.computed != null &&
!alreadyComputedFieldsLookup[resource.name + f.fieldName],
)
);
};

Expand All @@ -327,6 +336,7 @@ export class OData2AbstractSQL {
public defaultResource: Resource | undefined;
public bindVarsLength: number = 0;
private checkAlias: (alias: string) => string;
private alreadyComputedFields: AlreadyComputedFieldsLookup = {};

constructor(
private clientModel: RequiredAbstractSqlModelSubset,
Expand Down Expand Up @@ -543,7 +553,9 @@ export class OData2AbstractSQL {
// For updates/deletes that we use a `WHERE id IN (SELECT...)` subquery to apply options and in the case of a definition
// we make sure to always apply it. This means that the definition will still be applied for these queries
if (
(hasQueryOpts || isDynamicResource(resource) || pathKeyWhere != null) &&
(hasQueryOpts ||
isDynamicResource(resource, this.alreadyComputedFields) ||
pathKeyWhere != null) &&
(method === 'POST' || method === 'PUT-INSERT')
) {
// For insert statements we need to use an INSERT INTO ... SELECT * FROM (binds) WHERE ... style query
Expand All @@ -562,8 +574,9 @@ export class OData2AbstractSQL {
'SelectQuery',
[
'Select',
(resource.modifyFields ?? resource.fields).map(
(field): AliasNode<CastNode> => {
(resource.modifyFields ?? resource.fields)
.filter((field) => field.computed == null)
.map((field): AliasNode<CastNode> => {
const alias = field.fieldName;
const bindVar = bindVars?.find((v) => v[0] === alias);
const value = bindVar?.[1] ?? ['Null'];
Expand All @@ -573,8 +586,7 @@ export class OData2AbstractSQL {
);
}
return ['Alias', ['Cast', value, field.dataType], alias];
},
),
}),
],
],
'$insert',
Expand Down Expand Up @@ -687,7 +699,8 @@ export class OData2AbstractSQL {
// we make sure to always apply it. This means that the definition will still be applied for these queries, for insert queries
// this is handled when we set the 'Values'
if (
(hasQueryOpts || isDynamicResource(resource)) &&
(hasQueryOpts ||
isDynamicResource(resource, this.alreadyComputedFields)) &&
(method === 'PUT' ||
method === 'PATCH' ||
method === 'MERGE' ||
Expand Down Expand Up @@ -991,11 +1004,16 @@ export class OData2AbstractSQL {
fieldName: string,
computed?: AbstractSqlQuery,
alias: string = fieldName,
alwaysCompileComputed: boolean = false,
):
| ReferencedFieldNode
| AliasNode<ReferencedFieldNode>
| AliasNode<AbstractSqlQuery> {
if (computed) {
const key = resource.name + fieldName;
if (
computed &&
(!this.alreadyComputedFields[key] || alwaysCompileComputed)
) {
if (
resource.tableAlias != null &&
resource.tableAlias !== resource.name
Expand All @@ -1006,6 +1024,7 @@ export class OData2AbstractSQL {
resource.tableAlias,
);
}
this.alreadyComputedFields[key] = true;
return ['Alias', computed, alias];
}
const referencedField = this.ReferencedField(resource, fieldName);
Expand Down Expand Up @@ -1632,6 +1651,7 @@ export class OData2AbstractSQL {
this.putReset();
this.extraBodyVars = {};
this.extraBindVars = [] as unknown as ODataBinds;
this.alreadyComputedFields = {};
}

putReset() {
Expand Down Expand Up @@ -1695,6 +1715,7 @@ export class OData2AbstractSQL {
sqlNameToODataName(field.fieldName),
field.computed,
field.fieldName,
true,
),
),
];
Expand Down

0 comments on commit 870744d

Please sign in to comment.