Skip to content

Commit

Permalink
feat: support using custom index with SelectQueryBuilder in MySQL (#7755
Browse files Browse the repository at this point in the history
)

* Support using custom index for MySqlDriver.

* Update select-query-builder.md

Co-authored-by: Umed Khudoiberdiev <pleerock.me@gmail.com>
  • Loading branch information
Hong Truong and pleerock committed Nov 9, 2021
1 parent 4aaafdf commit f79ae58
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 2 deletions.
14 changes: 13 additions & 1 deletion docs/select-query-builder.md
Expand Up @@ -22,6 +22,7 @@
* [Streaming result data](#streaming-result-data)
* [Using pagination](#using-pagination)
* [Set locking](#set-locking)
* [Use custom index](#use-custom-index)
* [Max execution time](#max-execution-time)
* [Partial selection](#partial-selection)
* [Using subqueries](#using-subqueries)
Expand Down Expand Up @@ -916,9 +917,20 @@ const users = await getRepository(User)

Optimistic locking works in conjunction with both `@Version` and `@UpdatedDate` decorators.

## Use custom index

You can provide a certain index for database server to use in some cases. This feature is only supported in MySQL.

```typescript
const users = await getRepository(User)
.createQueryBuilder("user")
.useIndex("my_index") // name of index
.getMany();
```

## Max execution time

We can drop slow query to avoid crashing the server. Only MySQL driver is supported at the moment:
We can drop slow query to avoid crashing the server.

```typescript
const users = await getRepository(User)
Expand Down
7 changes: 7 additions & 0 deletions src/query-builder/QueryExpressionMap.ts
Expand Up @@ -157,6 +157,13 @@ export class QueryExpressionMap {
*/
take?: number;

/**
* Use certain index for the query.
*
* SELECT * FROM table_name USE INDEX (col1_index, col2_index) WHERE col1=1 AND col2=2 AND col3=3;
*/
useIndex?: string;

/**
* Locking mode.
*/
Expand Down
21 changes: 20 additions & 1 deletion src/query-builder/SelectQueryBuilder.ts
Expand Up @@ -966,6 +966,17 @@ export class SelectQueryBuilder<Entity> extends QueryBuilder<Entity> implements
return this;
}

/**
* Set certain index to be used by the query.
*
* @param index Name of index to be used.
*/
useIndex(index: string): this {
this.expressionMap.useIndex = index;

return this;
}

/**
* Sets locking mode.
*/
Expand Down Expand Up @@ -1441,6 +1452,14 @@ export class SelectQueryBuilder<Entity> extends QueryBuilder<Entity> implements
}
}

// Use certain index
let useIndex: string = "";
if (this.expressionMap.useIndex) {
if (this.connection.driver instanceof MysqlDriver) {
useIndex = ` USE INDEX (${this.expressionMap.useIndex})`;
}
}

// create a selection query
const froms = this.expressionMap.aliases
.filter(alias => alias.type === "from" && (alias.tablePath || alias.subQuery))
Expand All @@ -1454,7 +1473,7 @@ export class SelectQueryBuilder<Entity> extends QueryBuilder<Entity> implements
const select = this.createSelectDistinctExpression();
const selection = allSelects.map(select => select.selection + (select.aliasName ? " AS " + this.escape(select.aliasName) : "")).join(", ");

return select + selection + " FROM " + froms.join(", ") + lock;
return select + selection + " FROM " + froms.join(", ") + lock + useIndex;
}

/**
Expand Down
14 changes: 14 additions & 0 deletions test/functional/query-builder/select/query-builder-select.ts
Expand Up @@ -447,4 +447,18 @@ describe("query builder > select", () => {

expect(sql).contains("SELECT /*+ MAX_EXECUTION_TIME(1000) */");
})));

it("Support using certain index", () => Promise.all(connections.map(async connection => {
// `USE INDEX` is only supported in MySQL
if (!(connection.driver instanceof MysqlDriver)) {
return;
}

const sql = connection
.createQueryBuilder(Post, "post")
.useIndex("my_index")
.getSql();

expect(sql).contains("FROM post USE INDEX (my_index)");
})));
});

0 comments on commit f79ae58

Please sign in to comment.