diff --git a/extensions/dacpac/src/test/testDacFxService.ts b/extensions/dacpac/src/test/testDacFxService.ts index d87383ff12..16b5969b30 100644 --- a/extensions/dacpac/src/test/testDacFxService.ts +++ b/extensions/dacpac/src/test/testDacFxService.ts @@ -170,4 +170,7 @@ export class DacFxTestService implements mssql.IDacFxService { }; return Promise.resolve(streamingJobValidationResult); } + parseTSqlScript(filePath: string, databaseSchemaProvider: string): Thenable { + return Promise.resolve({ containsCreateTableStatement: true }); + } } diff --git a/extensions/mssql/config.json b/extensions/mssql/config.json index 4013a4f020..4bbd81246b 100644 --- a/extensions/mssql/config.json +++ b/extensions/mssql/config.json @@ -1,6 +1,6 @@ { "downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/{#version#}/microsoft.sqltools.servicelayer-{#fileName#}", - "version": "4.1.0.4", + "version": "4.1.0.9", "downloadFileNames": { "Windows_86": "win-x86-net6.0.zip", "Windows_64": "win-x64-net6.0.zip", diff --git a/extensions/mssql/src/contracts.ts b/extensions/mssql/src/contracts.ts index 34054babe9..e0c415eebc 100644 --- a/extensions/mssql/src/contracts.ts +++ b/extensions/mssql/src/contracts.ts @@ -545,6 +545,11 @@ export interface ValidateStreamingJobParams { createStreamingJobTsql: string } +export interface ParseTSqlScriptParams { + filePath: string; + databaseSchemaProvider: string; +} + export namespace ExportRequest { export const type = new RequestType('dacfx/export'); } @@ -577,6 +582,10 @@ export namespace ValidateStreamingJobRequest { export const type = new RequestType('dacfx/validateStreamingJob'); } +export namespace ParseTSqlScriptRequest { + export const type = new RequestType('dacfx/parseTSqlScript'); +} + // ------------------------------- ------------------------------------ // ------------------------------- ---------------------------------------- diff --git a/extensions/mssql/src/dacfx/dacFxService.ts b/extensions/mssql/src/dacfx/dacFxService.ts index 11634c6089..0f6b7d1a6c 100644 --- a/extensions/mssql/src/dacfx/dacFxService.ts +++ b/extensions/mssql/src/dacfx/dacFxService.ts @@ -130,4 +130,15 @@ export class DacFxService implements mssql.IDacFxService { } ); } + + public async parseTSqlScript(filePath: string, databaseSchemaProvider: string): Promise { + const params: contracts.ParseTSqlScriptParams = { filePath, databaseSchemaProvider }; + try { + const result = await this.client.sendRequest(contracts.ParseTSqlScriptRequest.type, params); + return result; + } catch (e) { + this.client.logFailedRequest(contracts.ParseTSqlScriptRequest.type, e); + throw e; + } + } } diff --git a/extensions/mssql/src/mssql.d.ts b/extensions/mssql/src/mssql.d.ts index 5b6b46e05f..fb8ec23ea1 100644 --- a/extensions/mssql/src/mssql.d.ts +++ b/extensions/mssql/src/mssql.d.ts @@ -391,6 +391,7 @@ declare module 'mssql' { generateDeployPlan(packageFilePath: string, databaseName: string, ownerUri: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable; getOptionsFromProfile(profilePath: string): Thenable; validateStreamingJob(packageFilePath: string, createStreamingJobTsql: string): Thenable; + parseTSqlScript(filePath: string, databaseSchemaProvider: string): Thenable; } export interface DacFxResult extends azdata.ResultStatus { @@ -408,6 +409,10 @@ declare module 'mssql' { export interface ValidateStreamingJobResult extends azdata.ResultStatus { } + export interface ParseTSqlScriptResult { + containsCreateTableStatement: boolean; + } + export interface ExportParams { databaseName: string; packageFilePath: string; diff --git a/extensions/sql-database-projects/src/models/project.ts b/extensions/sql-database-projects/src/models/project.ts index bdfc3a5f4b..9b9fbc6a6a 100644 --- a/extensions/sql-database-projects/src/models/project.ts +++ b/extensions/sql-database-projects/src/models/project.ts @@ -10,6 +10,7 @@ import * as utils from '../common/utils'; import * as xmlFormat from 'xml-formatter'; import * as os from 'os'; import * as UUID from 'vscode-languageclient/lib/utils/uuid'; +import * as mssql from 'mssql'; import { Uri, window } from 'vscode'; import { EntryType, IDatabaseReferenceProjectEntry, IProjectEntry, ISqlProject, ItemType, SqlTargetPlatform } from 'sqldbproj'; @@ -247,14 +248,19 @@ export class Project implements ISqlProject { const fileEntries: FileProjectEntry[] = []; for (let f of Array.from(filesSet.values())) { const typeEntry = entriesWithType.find(e => e.relativePath === f); - let containsCreateTableStatement; + let containsCreateTableStatement = false; // read file to check if it has a "Create Table" statement const fullPath = path.join(utils.getPlatformSafeFileEntryPath(this.projectFolderPath), utils.getPlatformSafeFileEntryPath(f)); - if (await utils.exists(fullPath)) { - const fileContents = await fs.readFile(fullPath); - containsCreateTableStatement = fileContents.toString().toLowerCase().includes('create table'); + if (utils.getAzdataApi()) { + const dacFxService = await utils.getDacFxService() as mssql.IDacFxService; + try { + const result = await dacFxService.parseTSqlScript(fullPath, this.getProjectTargetVersion()); + containsCreateTableStatement = result.containsCreateTableStatement; + } catch (e) { + console.error(utils.getErrorMessage(e)); + } } fileEntries.push(this.createFileProjectEntry(f, EntryType.File, typeEntry ? typeEntry.typeAttribute : undefined, containsCreateTableStatement)); diff --git a/extensions/sql-database-projects/src/test/testContext.ts b/extensions/sql-database-projects/src/test/testContext.ts index 5962c7065e..6012e09f67 100644 --- a/extensions/sql-database-projects/src/test/testContext.ts +++ b/extensions/sql-database-projects/src/test/testContext.ts @@ -140,6 +140,7 @@ export class MockDacFxService implements mssql.IDacFxService { public generateDeployPlan(_: string, __: string, ___: string, ____: azdata.TaskExecutionMode): Thenable { return Promise.resolve(mockDacFxResult); } public getOptionsFromProfile(_: string): Thenable { return Promise.resolve(mockDacFxOptionsResult); } public validateStreamingJob(_: string, __: string): Thenable { return Promise.resolve(mockDacFxResult); } + public parseTSqlScript(_: string, __: string): Thenable { return Promise.resolve({ containsCreateTableStatement: true }); } } export function createContext(): TestContext { diff --git a/extensions/sql-database-projects/src/test/testUtils.ts b/extensions/sql-database-projects/src/test/testUtils.ts index d4ac849726..5a9ce8651c 100644 --- a/extensions/sql-database-projects/src/test/testUtils.ts +++ b/extensions/sql-database-projects/src/test/testUtils.ts @@ -6,6 +6,7 @@ import * as path from 'path'; import * as os from 'os'; import * as constants from '../common/constants'; +import * as templates from '../templates/templates'; import { promises as fs } from 'fs'; import should = require('should'); @@ -34,6 +35,10 @@ export async function createTestSqlProjFile(contents: string, folderPath?: strin } export async function createTestProject(contents: string, folderPath?: string): Promise { + const macroDict: Record = { + 'PROJECT_DSP': constants.defaultDSP + }; + contents = templates.macroExpansion(contents, macroDict); return await Project.openProject(await createTestSqlProjFile(contents, folderPath)); }