From 189592c77980e766f92f6eb77dbd7412db106086 Mon Sep 17 00:00:00 2001 From: Patrick Molgaard Date: Fri, 20 May 2022 13:04:25 +0100 Subject: [PATCH] perf: don't recompile escapeRegExp for every query (#8956) Context: the query builder is pretty CPU intensive, and can be slow - e.g. https://github.com/typeorm/typeorm/issues/3857 One of the things which makes this slow is `escapeRegExp` in the query builder: we freshly construct the same RegExp once per `replacePropertyName` invocation (many times per overall query!) and since the RegExp itself is constant -- we can lift it out and construct it once. Over-all this saves about 8% on our query build times as measured by #8955. --- src/query-builder/QueryBuilder.ts | 7 ++----- src/util/escapeRegExp.ts | 4 ++++ 2 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 src/util/escapeRegExp.ts diff --git a/src/query-builder/QueryBuilder.ts b/src/query-builder/QueryBuilder.ts index c23f8cd376..c8d378b69f 100644 --- a/src/query-builder/QueryBuilder.ts +++ b/src/query-builder/QueryBuilder.ts @@ -24,6 +24,7 @@ import { EntityPropertyNotFoundError } from "../error/EntityPropertyNotFoundErro import { ReturningType } from "../driver/Driver" import { OracleDriver } from "../driver/oracle/OracleDriver" import { InstanceChecker } from "../util/InstanceChecker" +import { escapeRegExp } from "../util/escapeRegExp" // todo: completely cover query builder with tests // todo: entityOrProperty can be target name. implement proper behaviour if it is. @@ -701,12 +702,8 @@ export abstract class QueryBuilder { /** * Replaces all entity's propertyName to name in the given statement. */ - protected replacePropertyNames(statement: string) { - // Escape special characters in regular expressions - // Per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping - const escapeRegExp = (s: String) => - s.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&") + protected replacePropertyNames(statement: string) { for (const alias of this.expressionMap.aliases) { if (!alias.hasMetadata) continue const replaceAliasNamePrefix = this.expressionMap diff --git a/src/util/escapeRegExp.ts b/src/util/escapeRegExp.ts new file mode 100644 index 0000000000..05597f8a49 --- /dev/null +++ b/src/util/escapeRegExp.ts @@ -0,0 +1,4 @@ +// Escape special characters in regular expressions +// Per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping +const ESCAPE_REGEXP = /[.*+\-?^${}()|[\]\\]/g +export const escapeRegExp = (s: String) => s.replace(ESCAPE_REGEXP, "\\$&")