diff --git a/packages/nodes-base/nodes/MySql/test/v1/GenericFunctions.test.ts b/packages/nodes-base/nodes/MySql/test/v1/GenericFunctions.test.ts new file mode 100644 index 0000000000000..05f4a7835de95 --- /dev/null +++ b/packages/nodes-base/nodes/MySql/test/v1/GenericFunctions.test.ts @@ -0,0 +1,94 @@ +/* eslint-disable n8n-nodes-base/node-param-display-name-miscased */ +import mysql2 from 'mysql2/promise'; +import type { ILoadOptionsFunctions, INodeListSearchResult } from 'n8n-workflow'; + +import { searchTables } from '../../v1/GenericFunctions'; + +jest.mock('mysql2/promise'); + +describe('MySQL / v1 / Generic Functions', () => { + let mockLoadOptionsFunctions: ILoadOptionsFunctions; + + beforeEach(() => { + jest.resetAllMocks(); + + mockLoadOptionsFunctions = { + getCredentials: jest.fn().mockResolvedValue({ + database: 'test_db', + }), + } as unknown as ILoadOptionsFunctions; + }); + + describe('searchTables', () => { + it('should return matching tables', async () => { + const mockRows = [{ table_name: 'users' }, { table_name: 'products' }]; + + const mockQuery = jest.fn().mockResolvedValue([mockRows]); + const mockEnd = jest.fn().mockResolvedValue(undefined); + + (mysql2.createConnection as jest.Mock).mockResolvedValue({ + query: mockQuery, + end: mockEnd, + }); + + const result: INodeListSearchResult = await searchTables.call( + mockLoadOptionsFunctions, + 'user', + ); + + expect(result).toEqual({ + results: [ + { name: 'users', value: 'users' }, + { name: 'products', value: 'products' }, + ], + }); + + expect(mockQuery).toHaveBeenCalledWith( + `SELECT table_name +FROM information_schema.tables +WHERE table_schema = ? +AND table_name LIKE ? +ORDER BY table_name`, + ['test_db', '%user%'], + ); + + expect(mockEnd).toHaveBeenCalled(); + }); + + it('should handle empty search query', async () => { + const mockRows: any[] = []; + + const mockQuery = jest.fn().mockResolvedValue([mockRows]); + const mockEnd = jest.fn().mockResolvedValue(undefined); + + (mysql2.createConnection as jest.Mock).mockResolvedValue({ + query: mockQuery, + end: mockEnd, + }); + + const result = await searchTables.call(mockLoadOptionsFunctions); + + expect(result).toEqual({ results: [] }); + expect(mockQuery).toHaveBeenCalledWith( + `SELECT table_name +FROM information_schema.tables +WHERE table_schema = ? +AND table_name LIKE ? +ORDER BY table_name`, + ['test_db', '%%'], + ); + + expect(mockEnd).toHaveBeenCalled(); + }); + + it('should handle database errors', async () => { + const mockError = new Error('Database connection failed'); + + (mysql2.createConnection as jest.Mock).mockRejectedValue(mockError); + + await expect(searchTables.call(mockLoadOptionsFunctions)).rejects.toThrow( + 'Database connection failed', + ); + }); + }); +}); diff --git a/packages/nodes-base/nodes/MySql/v1/GenericFunctions.ts b/packages/nodes-base/nodes/MySql/v1/GenericFunctions.ts index 68b35a980d779..3cefb5a7d0be7 100644 --- a/packages/nodes-base/nodes/MySql/v1/GenericFunctions.ts +++ b/packages/nodes-base/nodes/MySql/v1/GenericFunctions.ts @@ -30,20 +30,21 @@ export async function createConnection( export async function searchTables( this: ILoadOptionsFunctions, - query?: string, + tableName?: string, ): Promise { const credentials = await this.getCredentials('mySql'); const connection = await createConnection(credentials); - const sql = ` - SELECT table_name FROM information_schema.tables - WHERE table_schema = '${credentials.database}' - and table_name like '%${query || ''}%' - ORDER BY table_name - `; - const [rows] = await connection.query(sql); - const results = (rows as IDataObject[]).map((r) => ({ - name: r.TABLE_NAME as string, - value: r.TABLE_NAME as string, + const sql = `SELECT table_name +FROM information_schema.tables +WHERE table_schema = ? +AND table_name LIKE ? +ORDER BY table_name`; + + const values = [credentials.database, `%${tableName ?? ''}%`]; + const [rows] = await connection.query(sql, values); + const results = (rows as IDataObject[]).map((table) => ({ + name: (table.table_name as string) || (table.TABLE_NAME as string), + value: (table.table_name as string) || (table.TABLE_NAME as string), })); await connection.end(); return { results };