From 82ec72d4fb8628c847b32d0ddf23a95119ca6ccf Mon Sep 17 00:00:00 2001 From: killa Date: Fri, 9 Aug 2024 13:08:10 +0800 Subject: [PATCH] fix: generate index name with column name (#230) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ##### Checklist - [ ] `npm test` passes - [ ] tests and/or benchmarks are included - [ ] documentation is changed or added - [ ] commit message follows commit guidelines ##### Affected core subsystem(s) ##### Description of change ## Summary by CodeRabbit - **New Features** - Enhanced index building functionality in the application by allowing class type references during index creation. - Introduced a new database table schema representation, improving the integration with ORM frameworks. - **Bug Fixes** - Improved error messages for clearer identification of issues related to missing columns in index creation. - **Tests** - Added a new test case for the SQL generator, ensuring accurate SQL generation for the new database table model. - Modified test logic to skip execution on macOS and Windows platforms, enhancing robustness. - **Chores** - Updated MySQL installation and startup commands in GitHub Actions for improved compatibility and simplicity. --- .github/workflows/nodejs.yml | 4 +- core/dal-decorator/src/model/IndexModel.ts | 8 +-- core/dal-decorator/src/model/TableModel.ts | 2 +- core/dal-runtime/test/SqlGenerator.test.ts | 17 +++++ .../test/fixtures/modules/dal/FooIndexName.ts | 63 +++++++++++++++++++ plugin/orm/test/fixtures/prepare.js | 2 +- plugin/orm/test/index.test.ts | 2 +- 7 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 core/dal-runtime/test/fixtures/modules/dal/FooIndexName.ts diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 48ea4a95..83fc072a 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -62,11 +62,11 @@ jobs: node-version: ${{ matrix.node-version }} - name: Install Mysql - run: brew install mysql@5.7 + run: brew install mysql - name: Start Mysql ## arm64/x86 homebrew mysql path different - run: /usr/local/opt/mysql@5.7/bin/mysql.server start || /opt/homebrew/Cellar/mysql@5.7/5.7.44_1/bin/mysql.server start + run: brew services start mysql - name: Install Npm run: npm i -g npm@9 diff --git a/core/dal-decorator/src/model/IndexModel.ts b/core/dal-decorator/src/model/IndexModel.ts index 924b160f..32029d39 100644 --- a/core/dal-decorator/src/model/IndexModel.ts +++ b/core/dal-decorator/src/model/IndexModel.ts @@ -1,4 +1,4 @@ -import { IndexType } from '@eggjs/tegg-types'; +import { EggProtoImplClass, IndexType } from '@eggjs/tegg-types'; import type { IndexParams, IndexStoreType } from '@eggjs/tegg-types'; import { ColumnModel } from './ColumnModel'; @@ -43,19 +43,19 @@ export class IndexModel { return prefix + keys.join('_'); } - static build(params: IndexParams, columns: ColumnModel[]) { + static build(params: IndexParams, columns: ColumnModel[], clazz: EggProtoImplClass) { const type = params.type ?? IndexType.INDEX; - const name = params.name ?? IndexModel.buildIndexName(params.keys, type); const keys: Array = params.keys.map(t => { const column = columns.find(c => c.propertyName === t); if (!column) { - throw new Error(`Index "${name}" configuration error: has no property named "${t}"`); + throw new Error(`Table ${clazz.name} index configuration error: has no property named "${t}"`); } return { propertyName: column!.propertyName, columnName: column!.columnName, }; }); + const name = params.name ?? IndexModel.buildIndexName(keys.map(t => t.columnName), type); return new IndexModel({ name, keys, diff --git a/core/dal-decorator/src/model/TableModel.ts b/core/dal-decorator/src/model/TableModel.ts index 89ded854..6c55b54b 100644 --- a/core/dal-decorator/src/model/TableModel.ts +++ b/core/dal-decorator/src/model/TableModel.ts @@ -113,7 +113,7 @@ export class TableModel { const indexList = IndexInfoUtil.getIndexList(clazz as EggProtoImplClass); for (const index of indexList) { - indices.push(IndexModel.build(index, columns)); + indices.push(IndexModel.build(index, columns, clazz)); } return new TableModel({ diff --git a/core/dal-runtime/test/SqlGenerator.test.ts b/core/dal-runtime/test/SqlGenerator.test.ts index 3e1d525c..b12189b1 100644 --- a/core/dal-runtime/test/SqlGenerator.test.ts +++ b/core/dal-runtime/test/SqlGenerator.test.ts @@ -3,6 +3,7 @@ import { TableModel } from '@eggjs/dal-decorator'; import { Foo } from './fixtures/modules/dal/Foo'; import { SqlGenerator } from '../src/SqlGenerator'; import { AutoUpdateTime } from './fixtures/modules/dal/AutoUpdateTime'; +import { FooIndexName } from './fixtures/modules/dal/FooIndexName'; describe('test/SqlGenerator.test.ts', () => { it('generator should work', () => { @@ -67,4 +68,20 @@ describe('test/SqlGenerator.test.ts', () => { ' date_4 TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) NOT NULL UNIQUE KEY\n' + ') ;'); }); + + it('generator index name should work', () => { + const generator = new SqlGenerator(); + const fooIndexNameTableModel = TableModel.build(FooIndexName); + const sql = generator.generate(fooIndexNameTableModel); + assert.equal(sql, 'CREATE TABLE IF NOT EXISTS egg_foo (\n' + + ' id INT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT \'the primary key\',\n' + + ' name VARCHAR(100) NOT NULL UNIQUE KEY,\n' + + ' col1 VARCHAR(100) NOT NULL,\n' + + ' bit_column BIT(10) NOT NULL,\n' + + ' bool_column BOOL NOT NULL,\n' + + ' FULLTEXT KEY idx_col1_bool_column (col1,bool_column) COMMENT \'index comment\\n\',\n' + + ' UNIQUE KEY uk_name_col1_bit_column (name,col1,bit_column) USING BTREE COMMENT \'index comment\\n\'\n' + + ') DEFAULT CHARACTER SET utf8mb4, DEFAULT COLLATE utf8mb4_unicode_ci, COMMENT=\'foo table\';', + ); + }); }); diff --git a/core/dal-runtime/test/fixtures/modules/dal/FooIndexName.ts b/core/dal-runtime/test/fixtures/modules/dal/FooIndexName.ts new file mode 100644 index 00000000..05453527 --- /dev/null +++ b/core/dal-runtime/test/fixtures/modules/dal/FooIndexName.ts @@ -0,0 +1,63 @@ +import { + Column, + ColumnType, + Index, + IndexStoreType, + IndexType, + Table, +} from '@eggjs/dal-decorator'; + +@Table({ + name: 'egg_foo', + comment: 'foo table', + characterSet: 'utf8mb4', + collate: 'utf8mb4_unicode_ci', +}) +@Index({ + keys: [ 'name', 'col1', 'bitColumn' ], + type: IndexType.UNIQUE, + storeType: IndexStoreType.BTREE, + comment: 'index comment\n', +}) +@Index({ + keys: [ 'col1', 'boolColumn' ], + type: IndexType.FULLTEXT, + comment: 'index comment\n', +}) +export class FooIndexName { + @Column({ + type: ColumnType.INT, + }, { + primaryKey: true, + autoIncrement: true, + comment: 'the primary key', + }) + id: number; + + @Column({ + type: ColumnType.VARCHAR, + length: 100, + }, { + uniqueKey: true, + }) + name: string; + + @Column({ + type: ColumnType.VARCHAR, + length: 100, + }, { + name: 'col1', + }) + col1: string; + + @Column({ + type: ColumnType.BIT, + length: 10, + }) + bitColumn: Buffer; + + @Column({ + type: ColumnType.BOOL, + }) + boolColumn: 0 | 1; +} diff --git a/plugin/orm/test/fixtures/prepare.js b/plugin/orm/test/fixtures/prepare.js index 501c3085..45c26228 100644 --- a/plugin/orm/test/fixtures/prepare.js +++ b/plugin/orm/test/fixtures/prepare.js @@ -55,7 +55,7 @@ async function init() { (async () => { try { // TODO win32 ci not support mysql - if (os.platform() === 'win32') { + if ([ 'darwin', 'win32' ].includes(os.platform())) { return; } connect(); diff --git a/plugin/orm/test/index.test.ts b/plugin/orm/test/index.test.ts index 2454d776..67c24d31 100644 --- a/plugin/orm/test/index.test.ts +++ b/plugin/orm/test/index.test.ts @@ -13,7 +13,7 @@ import { EggContext } from '@eggjs/tegg'; describe('plugin/orm/test/orm.test.ts', () => { // TODO win32 ci not support mysql - if (os.platform() === 'win32') { + if ([ 'darwin', 'win32' ].includes(os.platform())) { return; }