From d36742652efa8fffb7fe6e75281654893f0e049d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Galeran?= Date: Mon, 3 May 2021 16:11:18 +0200 Subject: [PATCH] fix(dbpull): fix url parsing (related #6546) (#6900) --- .../migrate/src/__tests__/DbPull.test.ts | 62 +++++++++++-------- .../__snapshots__/DbPull.test.ts.snap | 2 + src/packages/migrate/src/commands/DbPull.ts | 10 ++- src/packages/sdk/src/convertCredentials.ts | 2 +- 4 files changed, 47 insertions(+), 29 deletions(-) diff --git a/src/packages/migrate/src/__tests__/DbPull.test.ts b/src/packages/migrate/src/__tests__/DbPull.test.ts index b0404c46a3e1..2ff570476304 100644 --- a/src/packages/migrate/src/__tests__/DbPull.test.ts +++ b/src/packages/migrate/src/__tests__/DbPull.test.ts @@ -63,11 +63,12 @@ test('introspection --force', async () => { test('basic introspection with --url', async () => { ctx.fixture('introspection/sqlite') const introspect = new DbPull() - await introspect.parse(['--print', '--url', 'file:dev.db']) + const result = introspect.parse(['--print', '--url', 'file:dev.db']) + await expect(result).resolves.toBe('') expect(ctx.mocked['console.log'].mock.calls.join('\n')).toMatchSnapshot() }) -test('basic introspection with invalid --url', async () => { +test('basic introspection with invalid --url - empty host', async () => { ctx.fixture('introspection/sqlite') const introspect = new DbPull() const result = introspect.parse([ @@ -75,8 +76,19 @@ test('basic introspection with invalid --url', async () => { '--url', 'postgresql://root:prisma@/prisma', ]) + await expect(result).rejects.toThrowErrorMatchingInlineSnapshot(` + Error parsing connection string: empty host in database URL + + `) + expect(ctx.mocked['console.log'].mock.calls.join('\n')).toMatchSnapshot() +}) + +test('basic introspection with invalid --url', async () => { + ctx.fixture('introspection/sqlite') + const introspect = new DbPull() + const result = introspect.parse(['--print', '--url', 'invalidstring']) await expect(result).rejects.toThrowErrorMatchingInlineSnapshot( - `Invalid data source URL, see https://www.prisma.io/docs/reference/database-reference/connection-urls`, + `Unknown database type invalidstring:`, ) expect(ctx.mocked['console.log'].mock.calls.join('\n')).toMatchSnapshot() }) @@ -223,14 +235,14 @@ it('should succeed and keep changes to valid schema and output warnings when usi expect(ctx.mocked['console.error'].mock.calls.join('\n')) .toMatchInlineSnapshot(` - // *** WARNING *** - // - // These models were enriched with \`@@map\` information taken from the previous Prisma schema. - // - Model "AwesomeNewPost" - // - Model "AwesomeProfile" - // - Model "AwesomeUser" - // - `) + // *** WARNING *** + // + // These models were enriched with \`@@map\` information taken from the previous Prisma schema. + // - Model "AwesomeNewPost" + // - Model "AwesomeProfile" + // - Model "AwesomeUser" + // + `) expect(ctx.fs.read('prisma/reintrospection.prisma')).toStrictEqual( originalSchema, @@ -262,18 +274,18 @@ it('should fail when db is missing', async () => { const result = DbPull.new().parse([]) await expect(result).rejects.toThrowErrorMatchingInlineSnapshot(` - P4001 The introspected database was empty: + P4001 The introspected database was empty: - prisma db pull could not create any models in your schema.prisma file and you will not be able to generate Prisma Client with the prisma generate command. + prisma db pull could not create any models in your schema.prisma file and you will not be able to generate Prisma Client with the prisma generate command. - To fix this, you have two options: + To fix this, you have two options: - - manually create a table in your database (using SQL). - - make sure the database connection URL inside the datasource block in schema.prisma points to a database that is not empty (it must contain at least one table). + - manually create a table in your database (using SQL). + - make sure the database connection URL inside the datasource block in schema.prisma points to a database that is not empty (it must contain at least one table). - Then you can run prisma db pull again. + Then you can run prisma db pull again. - `) + `) }) it('should fail when db is empty', async () => { @@ -282,18 +294,18 @@ it('should fail when db is empty', async () => { const result = DbPull.new().parse([]) await expect(result).rejects.toThrowErrorMatchingInlineSnapshot(` - P4001 The introspected database was empty: + P4001 The introspected database was empty: - prisma db pull could not create any models in your schema.prisma file and you will not be able to generate Prisma Client with the prisma generate command. + prisma db pull could not create any models in your schema.prisma file and you will not be able to generate Prisma Client with the prisma generate command. - To fix this, you have two options: + To fix this, you have two options: - - manually create a table in your database (using SQL). - - make sure the database connection URL inside the datasource block in schema.prisma points to a database that is not empty (it must contain at least one table). + - manually create a table in your database (using SQL). + - make sure the database connection URL inside the datasource block in schema.prisma points to a database that is not empty (it must contain at least one table). - Then you can run prisma db pull again. + Then you can run prisma db pull again. - `) + `) }) it('should fail when Prisma schema is missing', async () => { diff --git a/src/packages/migrate/src/__tests__/__snapshots__/DbPull.test.ts.snap b/src/packages/migrate/src/__tests__/__snapshots__/DbPull.test.ts.snap index b392c86fffaf..7d8a2c70c07d 100644 --- a/src/packages/migrate/src/__tests__/__snapshots__/DbPull.test.ts.snap +++ b/src/packages/migrate/src/__tests__/__snapshots__/DbPull.test.ts.snap @@ -80,6 +80,8 @@ model User { // introspectionSchemaVersion: Prisma2, `; +exports[`basic introspection with invalid --url - empty host 2`] = `Prisma schema loaded from schema.prisma`; + exports[`basic introspection with invalid --url 2`] = `Prisma schema loaded from schema.prisma`; exports[`introspection --force 1`] = ` diff --git a/src/packages/migrate/src/commands/DbPull.ts b/src/packages/migrate/src/commands/DbPull.ts index 3484717dcd18..5a3c57ede56f 100644 --- a/src/packages/migrate/src/commands/DbPull.ts +++ b/src/packages/migrate/src/commands/DbPull.ts @@ -14,11 +14,13 @@ import { IntrospectionEngine, IntrospectionWarnings, IntrospectionSchemaVersion, - uriToCredentials, } from '@prisma/sdk' import { formatms } from '../utils/formatms' import fs from 'fs' -import { databaseTypeToConnectorType } from '@prisma/sdk/dist/convertCredentials' +import { + protocolToDatabaseType, + databaseTypeToConnectorType, +} from '@prisma/sdk/dist/convertCredentials' import { printDatasources } from '../utils/printDatasources' import { removeDatasource } from '../utils/removeDatasource' @@ -55,7 +57,9 @@ Instead of saving the result to the filesystem, you can also print it to stdout `) private printUrlAsDatasource(url: string): string { - const provider = databaseTypeToConnectorType(uriToCredentials(url).type) + const provider = databaseTypeToConnectorType( + protocolToDatabaseType(`${url.split(':')[0]}:`), + ) return printDatasources([ { diff --git a/src/packages/sdk/src/convertCredentials.ts b/src/packages/sdk/src/convertCredentials.ts index 5ccf1f563087..d067b38259f7 100644 --- a/src/packages/sdk/src/convertCredentials.ts +++ b/src/packages/sdk/src/convertCredentials.ts @@ -161,7 +161,7 @@ function databaseTypeToProtocol(databaseType: ConnectorType): string { } } -function protocolToDatabaseType(protocol: string): ConnectorType { +export function protocolToDatabaseType(protocol: string): ConnectorType { switch (protocol) { case 'postgresql:': case 'postgres:':