diff --git a/package.json b/package.json index f411ba3..9c86e9b 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,6 @@ "typescript": "^3.0.3" }, "dependencies": { - "data-api-client": "ArsenyYankovsky/data-api-client#support-date" + "data-api-client": "ArsenyYankovsky/data-api-client#support-postgres" } } diff --git a/src/query-transformer/index.ts b/src/query-transformer/index.ts new file mode 100644 index 0000000..55af87a --- /dev/null +++ b/src/query-transformer/index.ts @@ -0,0 +1,3 @@ +export * from './mysql-query-transformer' +export * from './postgres-query-transformer' +export * from './query-transformer' diff --git a/src/query-transformer/mysql-query-transformer.ts b/src/query-transformer/mysql-query-transformer.ts new file mode 100644 index 0000000..d0fc4a7 --- /dev/null +++ b/src/query-transformer/mysql-query-transformer.ts @@ -0,0 +1,70 @@ +import { QueryTransformer } from './query-transformer' + +export class MysqlQueryTransformer extends QueryTransformer { + protected transformQuery(query: string, parameters: any[]): string { + const quoteCharacters = ["'", '"'] + let newQueryString = '' + let currentQuote = null + let srcIndex = 0 + let destIndex = 0 + + for (let i = 0; i < query.length; i += 1) { + const currentCharacter = query[i] + const currentCharacterEscaped = i !== 0 && query[i - 1] === '\\' + + if (currentCharacter === '?' && !currentQuote) { + const parameter = parameters![srcIndex] + + if (Array.isArray(parameter)) { + const additionalParameters = parameter.map((_, index) => + `:param_${destIndex + index}`) + + newQueryString += additionalParameters.join(', ') + destIndex += additionalParameters.length + } else { + newQueryString += `:param_${destIndex}` + destIndex += 1 + } + srcIndex += 1 + } else { + newQueryString += currentCharacter + + if (quoteCharacters.includes(currentCharacter) && !currentCharacterEscaped) { + if (!currentQuote) { + currentQuote = currentCharacter + } else if (currentQuote === currentCharacter) { + currentQuote = null + } + } + } + } + + return newQueryString + } + + protected expandArrayParameters(parameters: any[]): any[] { + return parameters.reduce( + (expandedParameters, parameter) => { + if (Array.isArray(parameter)) { + expandedParameters.push(...parameter) + } else { + expandedParameters.push(parameter) + } + return expandedParameters + }, []) + } + + protected transformParameters(parameters?: any[]) { + if (!parameters) { + return parameters + } + + const expandedParameters = this.expandArrayParameters(parameters) + + return [expandedParameters.reduce( + (params, parameter, index) => { + params[`param_${index}`] = parameter + return params + }, {})] + } +} diff --git a/src/query-transformer/postgres-query-transformer.ts b/src/query-transformer/postgres-query-transformer.ts new file mode 100644 index 0000000..01e943f --- /dev/null +++ b/src/query-transformer/postgres-query-transformer.ts @@ -0,0 +1,42 @@ +import { QueryTransformer } from './query-transformer' + +export class PostgresQueryTransformer extends QueryTransformer { + protected transformQuery(query: string) { + const quoteCharacters = ["'", '"'] + let newQueryString = '' + let currentQuote = null + + for (let i = 0; i < query.length; i += 1) { + const currentCharacter = query[i] + const currentCharacterEscaped = i !== 0 && query[i - 1] === '\\' + + if (currentCharacter === '$' && !currentQuote) { + newQueryString += ':param_' + } else { + newQueryString += currentCharacter + + if (quoteCharacters.includes(currentCharacter) && !currentCharacterEscaped) { + if (!currentQuote) { + currentQuote = currentCharacter + } else if (currentQuote === currentCharacter) { + currentQuote = null + } + } + } + } + + return newQueryString + } + + protected transformParameters(parameters?: any[]) { + if (!parameters) { + return parameters + } + + return [parameters.reduce( + (params, parameter, index) => { + params[`param_${index + 1}`] = parameter + return params + }, {})] + } +} diff --git a/src/query-transformer/query-transformer.ts b/src/query-transformer/query-transformer.ts new file mode 100644 index 0000000..1e9d142 --- /dev/null +++ b/src/query-transformer/query-transformer.ts @@ -0,0 +1,20 @@ +export interface QueryTransformationResult { + queryString: string, + parameters: any[], +} + +export abstract class QueryTransformer { + public transformQueryAndParameters(query: string, srcParameters: any[] = []) { + if (!srcParameters.length) { + return { queryString: query, parameters: [] } + } + + const queryString = this.transformQuery(query, srcParameters) + const parameters = this.transformParameters(srcParameters) + return { queryString, parameters } + } + + protected abstract transformQuery(query: string, srcParameters: any[]): string + + protected abstract transformParameters(srcParameters?: any[]): any[] | undefined +} diff --git a/src/transform.utils.ts b/src/transform.utils.ts deleted file mode 100644 index c8923bd..0000000 --- a/src/transform.utils.ts +++ /dev/null @@ -1,69 +0,0 @@ -const transformQuery = (query: string, parameters: any[]): string => { - const quoteCharacters = ["'", '"'] - let newQueryString = '' - let currentQuote = null - let srcIndex = 0 - let destIndex = 0 - - for (let i = 0; i < query.length; i += 1) { - const currentCharacter = query[i] - const currentCharacterEscaped = i !== 0 && query[i - 1] === '\\' - - if (currentCharacter === '?' && !currentQuote) { - const parameter = parameters![srcIndex] - - if (Array.isArray(parameter)) { - const additionalParameters = parameter.map((_, index) => - `:param_${destIndex + index}`) - - newQueryString += additionalParameters.join(', ') - destIndex += additionalParameters.length - } else { - newQueryString += `:param_${destIndex}` - destIndex += 1 - } - srcIndex += 1 - } else { - newQueryString += currentCharacter - - if (quoteCharacters.includes(currentCharacter) && !currentCharacterEscaped) { - if (!currentQuote) { - currentQuote = currentCharacter - } else if (currentQuote === currentCharacter) { - currentQuote = null - } - } - } - } - - return newQueryString -} - -const transformParameters = (parameters: any[]) => - parameters.reduce( - (params, parameter, index) => { - params[`param_${index}`] = parameter - return params - }, {}) - -const expandArrayParameters = (parameters: any[]) => - parameters.reduce( - (expandedParameters, parameter) => { - if (Array.isArray(parameter)) { - expandedParameters.push(...parameter) - } else { - expandedParameters.push(parameter) - } - return expandedParameters - }, []) - -export const transformQueryAndParameters = (query: string, srcParameters: any[] = []) => { - if (!srcParameters.length) { - return { queryString: query, parameters: [] } - } - - const queryString = transformQuery(query, srcParameters) - const expandedParameters = expandArrayParameters(srcParameters) - const parameters = [transformParameters(expandedParameters)] - return { queryString, parameters } -} diff --git a/src/typeorm-aurora-data-api-driver.ts b/src/typeorm-aurora-data-api-driver.ts index c38d9da..6457add 100644 --- a/src/typeorm-aurora-data-api-driver.ts +++ b/src/typeorm-aurora-data-api-driver.ts @@ -1,8 +1,8 @@ // @ts-ignore import createDataApiClient from 'data-api-client' -import { transformQueryAndParameters } from './transform.utils' +import { MysqlQueryTransformer, PostgresQueryTransformer, QueryTransformer } from './query-transformer' -export default class DataApiDriver { +class DataApiDriver { private readonly client: any private transactionId?: string @@ -12,6 +12,7 @@ export default class DataApiDriver { private readonly resourceArn: string, private readonly database: string, private readonly loggerFn: (query: string, parameters?: any[]) => void = () => undefined, + private readonly queryTransformer: QueryTransformer, private readonly serviceConfigOptions?: any, ) { this.region = region @@ -27,10 +28,11 @@ export default class DataApiDriver { database, options: this.serviceConfigOptions, }) + this.queryTransformer = queryTransformer } public async query(query: string, parameters?: any[]): Promise { - const transformedQueryData = transformQueryAndParameters(query, parameters) + const transformedQueryData = this.queryTransformer.transformQueryAndParameters(query, parameters) this.loggerFn(transformedQueryData.queryString, transformedQueryData.parameters) @@ -58,3 +60,36 @@ export default class DataApiDriver { this.transactionId = undefined } } + +const createMysqlDriver = (region: string, secretArn: string, resourceArn: string, database: string, + loggerFn: (query: string, parameters?: any[]) => void = () => undefined, + serviceConfigOptions?: any) => { + + return new DataApiDriver( + region, + secretArn, + resourceArn, + database, + loggerFn, + new MysqlQueryTransformer(), + serviceConfigOptions, + ) +} + +export default createMysqlDriver + +const createPostgresDriver = (region: string, secretArn: string, resourceArn: string, database: string, + loggerFn: (query: string, parameters?: any[]) => void = () => undefined, + serviceConfigOptions?: any) => { + return new DataApiDriver( + region, + secretArn, + resourceArn, + database, + loggerFn, + new PostgresQueryTransformer(), + serviceConfigOptions, + ) +} + +export const pg = createPostgresDriver diff --git a/test/functional/basic/entity/Category.ts b/test/functional/mysql/entity/Category.ts similarity index 100% rename from test/functional/basic/entity/Category.ts rename to test/functional/mysql/entity/Category.ts diff --git a/test/functional/basic/entity/Post.ts b/test/functional/mysql/entity/Post.ts similarity index 100% rename from test/functional/basic/entity/Post.ts rename to test/functional/mysql/entity/Post.ts diff --git a/test/functional/basic/simple-queries.func.test.ts b/test/functional/mysql/simple-queries.func.test.ts similarity index 88% rename from test/functional/basic/simple-queries.func.test.ts rename to test/functional/mysql/simple-queries.func.test.ts index 5d9330b..987cb50 100644 --- a/test/functional/basic/simple-queries.func.test.ts +++ b/test/functional/mysql/simple-queries.func.test.ts @@ -7,12 +7,12 @@ describe('aurora data api > simple queries', () => { jest.setTimeout(240000) it('should do a simple select', async () => { - await useCleanDatabase({ logger: 'simple-console' }, async (connection) => { + await useCleanDatabase('mysql', { logger: 'simple-console' }, async (connection) => { const logSpy = jest.spyOn(global.console, 'log') - const result = await connection.query('select 1') + const result = await connection.query('select 1 as \"1\"') - expect(logSpy).toHaveBeenCalledWith('query: select 1') + expect(logSpy).toHaveBeenCalledWith('query: select 1 as \"1\"') expect(logSpy).toBeCalledTimes(1) expect(result[0][1]).toBe(1) @@ -20,7 +20,7 @@ describe('aurora data api > simple queries', () => { }) it('should create a table and be able to query it', async () => { - await useCleanDatabase({ entities: [Post, Category] }, async (connection) => { + await useCleanDatabase('mysql', { entities: [Post, Category] }, async (connection) => { const postRepository = connection.getRepository(Post) const post = new Post() @@ -40,7 +40,7 @@ describe('aurora data api > simple queries', () => { }) it('should be able to update a post', async () => { - await useCleanDatabase({ entities: [Post, Category] }, async (connection) => { + await useCleanDatabase('mysql', { entities: [Post, Category] }, async (connection) => { const postRepository = connection.getRepository(Post) @@ -72,7 +72,7 @@ describe('aurora data api > simple queries', () => { }) it('should be able to handle dates and multiple inserts', async () => { - await useCleanDatabase({ entities: [Post, Category] }, async (connection) => { + await useCleanDatabase('mysql', { entities: [Post, Category] }, async (connection) => { const postRepository = connection.getRepository(Post) const post = new Post() @@ -104,7 +104,7 @@ describe('aurora data api > simple queries', () => { }) it('should be able to create and query a many-to-many relationship', async () => { - await useCleanDatabase({ entities: [Post, Category] }, async (connection) => { + await useCleanDatabase('mysql', { entities: [Post, Category] }, async (connection) => { // Create categories const categoryRepository = connection.getRepository(Category) @@ -144,7 +144,7 @@ describe('aurora data api > simple queries', () => { }) it('should be able to update a date field by primary key', async () => { - await useCleanDatabase({ entities: [Post, Category] }, async (connection) => { + await useCleanDatabase('mysql', { entities: [Post, Category] }, async (connection) => { // Create a post and associate with created categories const postRepository = connection.getRepository(Post) @@ -174,7 +174,7 @@ describe('aurora data api > simple queries', () => { }) it('should be able to correctly deal with bulk inserts', async () => { - await useCleanDatabase({ entities: [Category] }, async (connection) => { + await useCleanDatabase('mysql', { entities: [Category] }, async (connection) => { const categoryNames = ['one', 'two', 'three', 'four'] const newCategories = categoryNames.map(name => ({ name })) diff --git a/test/functional/pg/basic/entity/Category.ts b/test/functional/pg/basic/entity/Category.ts new file mode 100644 index 0000000..1038116 --- /dev/null +++ b/test/functional/pg/basic/entity/Category.ts @@ -0,0 +1,11 @@ +import { Column, Entity, Generated, PrimaryColumn } from 'typeorm' + +@Entity('category', { schema: 'test1' }) +export class Category { + @PrimaryColumn() + @Generated() + public id!: number + + @Column() + public name!: string +} diff --git a/test/functional/pg/basic/entity/Post.ts b/test/functional/pg/basic/entity/Post.ts new file mode 100644 index 0000000..2945520 --- /dev/null +++ b/test/functional/pg/basic/entity/Post.ts @@ -0,0 +1,28 @@ +import { Column, Entity, Generated, JoinTable, ManyToMany, PrimaryColumn } from 'typeorm' +import { Category } from './Category' + +@Entity('post', { schema: 'test1' }) +export class Post { + @PrimaryColumn() + @Generated() + public id!: number + + @Column() + public title!: string + + @Column() + public text!: string + + @Column({ nullable: false }) + public likesCount!: number + + @Column({ nullable: false, type: 'timestamp', default: () => 'now()' }) + public publishedAt!: Date + + @Column({ nullable: true, type: 'timestamp' }) + public updatedAt?: Date + + @ManyToMany(type => Category) + @JoinTable() + public categories!: Category[] +} diff --git a/test/functional/pg/basic/pg-simple-queries.func.test.ts b/test/functional/pg/basic/pg-simple-queries.func.test.ts new file mode 100644 index 0000000..c4c96cd --- /dev/null +++ b/test/functional/pg/basic/pg-simple-queries.func.test.ts @@ -0,0 +1,200 @@ +import 'reflect-metadata' +import { useCleanDatabase } from '../../utils/create-connection' +import { Category } from './entity/Category' +import { Post } from './entity/Post' + +describe('aurora data api pg > simple queries', () => { + jest.setTimeout(240000) + + it('should do a simple select', async () => { + await useCleanDatabase('postgres', { logger: 'simple-console' }, async (connection) => { + const logSpy = jest.spyOn(global.console, 'log') + + const result = await connection.query('select 1 as \"1\"') + + expect(logSpy).toHaveBeenCalledWith('query: select 1 as \"1\"') + expect(logSpy).toBeCalledTimes(1) + + expect(result[0][1]).toBe(1) + }) + }) + + it('should create a table and be able to query it', async () => { + await useCleanDatabase('postgres', { entities: [Post, Category] }, async (connection) => { + const postRepository = connection.getRepository(Post) + + const post = new Post() + post.title = 'My First Post' + post.text = 'Post Text' + post.likesCount = 4 + + const insertResult = await postRepository.save(post) + + const dbPost = await postRepository.findOne({ id: insertResult.id }) + expect(dbPost).toBeTruthy() + + expect(dbPost!.title).toBe('My First Post') + expect(dbPost!.text).toBe('Post Text') + expect(dbPost!.likesCount).toBe(4) + }) + }) + + it('should be able to update a post', async () => { + await useCleanDatabase('postgres', { entities: [Post, Category] }, async (connection) => { + + const postRepository = connection.getRepository(Post) + + const post = new Post() + + post.title = 'My First Post' + post.text = 'Post Text' + post.likesCount = 4 + post.publishedAt = new Date(2017, 1, 1) + + const insertResult = await postRepository.save(post) + + const postId = insertResult.id + + const dbPost = await postRepository.findOne({ id: postId }) + + dbPost!.publishedAt = new Date() + + await postRepository.save(dbPost!) + + const updatedPost = await postRepository.findOne(postId) + + expect(updatedPost!.publishedAt > new Date(2017, 1, 1)).toBeTruthy() + + expect(dbPost!.title).toBe('My First Post') + expect(dbPost!.text).toBe('Post Text') + expect(dbPost!.likesCount).toBe(4) + }) + }) + + it('should be able to handle dates and multiple inserts', async () => { + await useCleanDatabase('postgres', { entities: [Post, Category] }, async (connection) => { + const postRepository = connection.getRepository(Post) + + const post = new Post() + post.title = 'My First Post' + post.text = 'Post Text' + post.likesCount = 4 + post.publishedAt = new Date() + + const secondPost = new Post() + secondPost.title = 'My Second Post' + secondPost.text = 'Post Text' + secondPost.likesCount = 5 + secondPost.publishedAt = new Date() + + await postRepository.save([post, secondPost]) + + const dbPosts = await postRepository.find() + expect(dbPosts).toBeTruthy() + expect(dbPosts.length).toBe(2) + + for (const dbPost of dbPosts) { + expect(typeof dbPost!.title).toBe('string') + expect(typeof dbPost!.text).toBe('string') + expect(typeof dbPost!.likesCount).toBe('number') + + expect(dbPost!.publishedAt).toBeInstanceOf(Date) + } + }) + }) + + it('should be able to create and query a many-to-many relationship', async () => { + await useCleanDatabase('postgres', { entities: [Post, Category] }, async (connection) => { + // Create categories + const categoryRepository = connection.getRepository(Category) + + const firstCategory = await categoryRepository.save( + categoryRepository.create({ + name: 'first', + }), + ) + + const secondCategory = await categoryRepository.save( + categoryRepository.create({ + name: 'second', + }), + ) + + // Create a post and associate with created categories + const postRepository = connection.getRepository(Post) + + const post = postRepository.create({ + title: 'Post with categories', + text: 'Text', + likesCount: 6, + publishedAt: new Date(), + categories: [firstCategory, secondCategory], + }) + + const storedPost = await postRepository.save(post) + + // Assert + const dbPost = await postRepository.findOne( + storedPost.id, { relations: ['categories'] }) + + expect(dbPost).toBeTruthy() + expect(dbPost!.categories).toBeTruthy() + expect(dbPost!.categories.length).toBe(2) + }) + }) + + it('should be able to update a date field by primary key', async () => { + await useCleanDatabase('postgres', { entities: [Post, Category] }, async (connection) => { + // Create a post and associate with created categories + const postRepository = connection.getRepository(Post) + + const storedPost = await postRepository.save( + postRepository.create({ + title: 'Post For Update', + text: 'Text', + likesCount: 6, + publishedAt: new Date(), + }), + ) + + // Retrieve the post and update the date + const getPost = await postRepository.findOne(storedPost.id) + expect(getPost).toBeTruthy() + expect(getPost!.updatedAt).toBeFalsy() + + const updatedAt = new Date() + getPost!.updatedAt = updatedAt + await postRepository.save(getPost!) + + // Assert + const dbPost = await postRepository.findOne(storedPost.id) + expect(dbPost).toBeTruthy() + expect(Math.trunc(dbPost!.updatedAt!.getTime() / 1000)).toEqual(Math.trunc(updatedAt.getTime() / 1000)) + }) + }) + + it('should be able to correctly deal with bulk inserts', async () => { + await useCleanDatabase('postgres', { entities: [Category] }, async (connection) => { + const categoryNames = ['one', 'two', 'three', 'four'] + const newCategories = categoryNames.map(name => ({ name })) + + await connection.createQueryBuilder() + .insert() + .into(Category) + .values(newCategories) + .orIgnore() + .execute() + + // Query back the inserted categories + const categoryRepository = connection.getRepository(Category) + const categories = await categoryRepository.find() + + // Assert + expect(categories.length).toBe(4) + expect(categories[0].name = 'one') + expect(categories[1].name = 'two') + expect(categories[2].name = 'three') + expect(categories[3].name = 'four') + }) + }) +}) diff --git a/test/functional/utils/create-connection.ts b/test/functional/utils/create-connection.ts index 08207b9..edca628 100644 --- a/test/functional/utils/create-connection.ts +++ b/test/functional/utils/create-connection.ts @@ -4,13 +4,14 @@ import { createConnection as typeormCreateConnection, } from 'typeorm' -export const createConnection = async (partialOptions: Partial = {}) => { +export const createConnection = async (dbType: DbType, partialOptions: Partial = {}) => { return typeormCreateConnection({ ...partialOptions, - type: 'aurora-data-api', - database: process.env.database!, - secretArn: process.env.secretArn!, - resourceArn: process.env.resourceArn!, + name: dbType, + type: dbType === 'mysql' ? 'aurora-data-api' : 'aurora-data-api-pg', + database: process.env[`${dbType}Database`]!, + secretArn: process.env[`${dbType}SecretArn`]!, + resourceArn: process.env[`${dbType}ResourceArn`]!, region: process.env.region!, logging: true, logger: 'simple-console', @@ -28,21 +29,31 @@ export const createConnection = async (partialOptions: Partial = {}, ) => { - const connection = await createConnection({ ...partialOptions, synchronize: false }) - await connection.query(`DROP DATABASE IF EXISTS ${process.env.database};`) - await connection.query(`CREATE DATABASE ${process.env.database};`) - await connection.query(`USE ${process.env.database};`) + const connection = await createConnection(dbType, { ...partialOptions, synchronize: false }) + if (dbType === 'mysql') { + await connection.query(`DROP DATABASE IF EXISTS ${process.env.database};`) + await connection.query(`CREATE DATABASE ${process.env.database};`) + await connection.query(`USE ${process.env.database};`) + } else { + await connection.query('DROP schema IF EXISTS test1 CASCADE;') + await connection.query('CREATE schema test1;') + await connection.query('SET search_path = test1;') + } await connection.synchronize(true) return connection } +export type DbType = 'mysql' | 'postgres' + export const useCleanDatabase = async ( + dbType: DbType, partialOptions: Partial = {}, invoke: (connection: Connection) => Promise, ) => { - const connection = await createConnectionAndResetData(partialOptions) + const connection = await createConnectionAndResetData(dbType, partialOptions) try { await invoke(connection) } finally { diff --git a/test/transform-query.unit.test.ts b/test/transform-query.unit.test.ts index a577c51..b763af6 100644 --- a/test/transform-query.unit.test.ts +++ b/test/transform-query.unit.test.ts @@ -1,9 +1,11 @@ -import { transformQueryAndParameters } from '../src/transform.utils' +import { MysqlQueryTransformer } from '../src/query-transformer' describe('aurora data api > query transformation', () => { + const transformer = new MysqlQueryTransformer() + it('should correctly transform a query with no parameters', async () => { const query = 'select 1' - const result = transformQueryAndParameters(query) + const result = transformer.transformQueryAndParameters(query) expect(result.queryString).toEqual('select 1') expect(result.parameters).toEqual([]) @@ -11,7 +13,7 @@ describe('aurora data api > query transformation', () => { it('should correctly transform a query with empty parameters', async () => { const query = 'select 1' - const result = transformQueryAndParameters(query, []) + const result = transformer.transformQueryAndParameters(query, []) expect(result.queryString).toEqual('select 1') expect(result.parameters).toEqual([]) @@ -21,7 +23,7 @@ describe('aurora data api > query transformation', () => { const query = 'select * from posts where id = ?' const parameters = [1] - const result = transformQueryAndParameters(query, parameters) + const result = transformer.transformQueryAndParameters(query, parameters) expect(result.queryString).toEqual('select * from posts where id = :param_0') expect(result.parameters).toEqual([{ param_0: 1 }]) @@ -31,7 +33,7 @@ describe('aurora data api > query transformation', () => { const query = 'select * from posts where id = ? and text = "?" and title = "\\"?\\""' const parameters = [1] - const result = transformQueryAndParameters(query, parameters) + const result = transformer.transformQueryAndParameters(query, parameters) expect(result.queryString).toEqual( 'select * from posts where id = :param_0 and text = "?" and title = "\\"?\\""', @@ -44,7 +46,7 @@ describe('aurora data api > query transformation', () => { "select * from posts where id = ? and text = '?' and title = '\\'?\\'' and description = \"'?'\"" const parameters = [1] - const result = transformQueryAndParameters(query, parameters) + const result = transformer.transformQueryAndParameters(query, parameters) expect(result.queryString).toEqual( "select * from posts where id = :param_0 and text = '?' and title = '\\'?\\'' and description = \"'?'\"", @@ -62,7 +64,7 @@ describe('aurora data api > query transformation', () => { group by DATE(CONVERT_TZ(dateTime, 'UTC', 'UTC')) order by dateTime asc ` - const result = transformQueryAndParameters(query, [1, 2, 3]) + const result = transformer.transformQueryAndParameters(query, [1, 2, 3]) expect(result.parameters).toEqual([{ param_0: 1, param_1: 2, param_2: 3 }]) }) @@ -72,7 +74,7 @@ describe('aurora data api > query transformation', () => { const id = 'dd32d900-3df6-45b9-a253-70a4516b88dc' const id2 = 'some-guid' - const result = transformQueryAndParameters(query, [id, [id, id2, id, id2]]) + const result = transformer.transformQueryAndParameters(query, [id, [id, id2, id, id2]]) expect(result.queryString).toEqual( 'select * from posts where id in (:param_0) and id in (:param_1, :param_2, :param_3, :param_4)', @@ -88,7 +90,7 @@ describe('aurora data api > query transformation', () => { const id = 'dd32d900-3df6-45b9-a253-70a4516b88dc' const id2 = 'some-guid' const id3 = 'some-other-guid' - const result = transformQueryAndParameters(query, [[id, id2, id, id2], [id3, id2, id, id3]]) + const result = transformer.transformQueryAndParameters(query, [[id, id2, id, id2], [id3, id2, id, id3]]) expect(result.queryString).toEqual( 'select * from posts where id in (:param_0, :param_1, :param_2, :param_3) and test in (:param_4, :param_5, :param_6, :param_7);', diff --git a/yarn.lock b/yarn.lock index 1decdf9..4586684 100644 --- a/yarn.lock +++ b/yarn.lock @@ -719,9 +719,9 @@ atob@^2.1.1: integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== aws-sdk@^2.492.0: - version "2.548.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.548.0.tgz#20a3c7a77e1c6fd694cdb5e0ecc0ccf0d0542674" - integrity sha512-dnG1MEc3uOonGDswHPiq7TYn6EOG3+IQhF2LSRambz9adaZxwRgFOII7UVPJjh33FtxKpMzOSmf62R+EX822Nw== + version "2.634.0" + resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.634.0.tgz#95077c191107b9cb696e922b06e79949dcd13434" + integrity sha512-cZfRD7bcKBHOLoHUJuqB9xaLs/z1/xsc9zfGLIzyuxKLJa7Z0pxy8Y/0GrhWO98yXLBvLLET7btj2iDI2oWWhQ== dependencies: buffer "4.9.1" events "1.1.1" @@ -1727,9 +1727,9 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -data-api-client@ArsenyYankovsky/data-api-client#support-date: +data-api-client@ArsenyYankovsky/data-api-client#support-postgres: version "1.0.0-beta" - resolved "https://codeload.github.com/ArsenyYankovsky/data-api-client/tar.gz/2880f8f7456fc126d356b26fb2ddbac5903ed23f" + resolved "https://codeload.github.com/ArsenyYankovsky/data-api-client/tar.gz/043f3320f8d665c21250d615101e7b3bc8f1d298" dependencies: sqlstring "^2.3.1" @@ -7059,9 +7059,9 @@ sprintf-js@~1.0.2: integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sqlstring@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.1.tgz#475393ff9e91479aea62dcaf0ca3d14983a7fb40" - integrity sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A= + version "2.3.2" + resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.2.tgz#cdae7169389a1375b18e885f2e60b3e460809514" + integrity sha512-vF4ZbYdKS8OnoJAWBmMxCQDkiEBkGQYU7UZPtL8flbDRSNkhaXvRJ279ZtI6M+zDaQovVU4tuRgzK5fVhvFAhg== sshpk@^1.7.0: version "1.16.1"