Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Datacoves' dbt-core-interface improvements + new response #144

Merged
merged 4 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 18 additions & 24 deletions src/features/helper/dbtInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export enum DbtInterfaceErrorCode {
CompileSqlFailure = 1,
ExecuteSqlFailure = 2,
ProjectParseFailure = 3,
UnlintableUnfixable = 0,
}

export interface DbtInterfaceErrorContainer {
Expand All @@ -40,6 +41,16 @@ export interface DbtInterfaceErrorContainer {
};
}

const projectNotRegisteredError: DbtInterfaceErrorContainer = {
error: {
code: DbtInterfaceErrorCode.CompileSqlFailure,
message: "Sqlfluff currently unavailable. Check that your project does not contain compilation errors.",
data: {
error: "",
},
},
};

export class DbtInterface {
private sql: string | undefined;
private sql_path: string | undefined;
Expand All @@ -52,7 +63,9 @@ export class DbtInterface {
}

public getLintURL(): string {
let url = `http://${Configuration.dbtInterfaceHost()}:${Configuration.dbtInterfacePort()}/lint?sql_path=${this.sql_path}`;
let url = `http://${Configuration.dbtInterfaceHost()}:${Configuration.dbtInterfacePort()}/lint?sql_path=${
this.sql_path
}`;
if (this.sql !== undefined) {
url = `http://${Configuration.dbtInterfaceHost()}:${Configuration.dbtInterfacePort()}/lint?`;
}
Expand All @@ -68,7 +81,9 @@ export class DbtInterface {
// This endpoint is equivalent to "sqlfluff format". The behavior is
// _similar_ to "sqlfluff fix", but it applies a different set of rules.
// https://docs.sqlfluff.com/en/stable/cli.html#sqlfluff-format
let url = `http://${Configuration.dbtInterfaceHost()}:${Configuration.dbtInterfacePort()}/format?sql_path=${this.sql_path}`;
let url = `http://${Configuration.dbtInterfaceHost()}:${Configuration.dbtInterfacePort()}/format?sql_path=${
this.sql_path
}`;
if (this.sql !== undefined) {
url = `http://${Configuration.dbtInterfaceHost()}:${Configuration.dbtInterfacePort()}/format?`;
}
Expand All @@ -91,7 +106,7 @@ export class DbtInterface {
{
method: "GET",
signal: abortController.signal as AbortSignal,
},
}
);
if (response.status === 200) {
return true;
Expand All @@ -116,16 +131,6 @@ export class DbtInterface {
},
};

const projectNotRegisteredError: DbtInterfaceErrorContainer = {
error: {
code: DbtInterfaceErrorCode.FailedToReachServer,
message: "dbt project not registered",
data: {
error: "",
},
},
};

if (!(await this.healthCheck())) {
Utilities.appendHyphenatedLine();
Utilities.outputChannel.appendLine("Unhealthy dbt project:");
Expand Down Expand Up @@ -170,16 +175,6 @@ export class DbtInterface {
},
};

const projectNotRegisteredError: DbtInterfaceErrorContainer = {
error: {
code: DbtInterfaceErrorCode.FailedToReachServer,
message: "dbt project not registered",
data: {
error: "",
},
},
};

if (!(await this.healthCheck())) {
Utilities.appendHyphenatedLine();
Utilities.outputChannel.appendLine("Unhealthy dbt project:");
Expand All @@ -192,7 +187,6 @@ export class DbtInterface {
abortController.abort();
}, timeout);
let response: Response;

try {
response = await fetch(encodeURI(this.getFormatURL()), {
method: "POST",
Expand Down
57 changes: 41 additions & 16 deletions src/features/providers/sqlfluff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { StringDecoder } from "string_decoder";
import * as vscode from "vscode";

import Configuration from "../helper/configuration";
import { DbtInterface } from "../helper/dbtInterface";
import { DbtInterface, DbtInterfaceErrorCode } from "../helper/dbtInterface";
import { LineDecoder } from "../helper/lineDecoder";
import Utilities from "../helper/utilities";
import FilePath from "./linter/types/filePath";
Expand All @@ -14,6 +14,7 @@ import CommandType from "./types/commandType";

export default class SQLFluff {
static childProcesses: CProcess.ChildProcess[] = [];
static shownDbtInterfacePopup: boolean = false;
static version: [major: number, minor: number, patch: number];

static isForceDeprecated = () => {
Expand All @@ -28,7 +29,7 @@ export default class SQLFluff {
workingDirectory: string | undefined,
command: CommandType,
args: string[],
options: CommandOptions,
options: CommandOptions
): Promise<CommandOutput> {
if (!options.fileContents && !options.filePath) {
throw new Error("You must supply either a target file path or the file contents to scan");
Expand All @@ -42,7 +43,7 @@ export default class SQLFluff {
const dbtInterface = new DbtInterface(
undefined,
options.workspacePath ?? options.filePath,
Configuration.config(),
Configuration.config()
);

Utilities.outputChannel.appendLine("\n--------------------Executing Command--------------------\n");
Expand All @@ -68,16 +69,27 @@ export default class SQLFluff {
Utilities.outputChannel.appendLine(JSON.stringify(response, undefined, 2));
Utilities.appendHyphenatedLine();

return new Promise<CommandOutput>((resolve) => {
return new Promise<CommandOutput>(async (resolve) => {
const code = response?.error?.code ?? 0;
const succeeded = code === 0;
if (!succeeded && !Configuration.suppressNotifications()) {
const succeeded = code === 0 && !response?.error;
if (!succeeded && !Configuration.suppressNotifications() && !this.shownDbtInterfacePopup) {
const message = response?.error?.message ?? "DBT-Interface formatting error.";
const detail = response?.error?.data?.error ?? "";

vscode.window.showErrorMessage([message, detail].join("\n"));
if (code === DbtInterfaceErrorCode.CompileSqlFailure) {
this.shownDbtInterfacePopup = true;
const runDbt = "Debug by running dbt Compile";
const chosen = await vscode.window.showErrorMessage(message, runDbt);
if (chosen === runDbt) {
await vscode.commands.executeCommand("dbtPowerUser.dbtCompile");
}
} else if (code === DbtInterfaceErrorCode.UnlintableUnfixable) {
vscode.window.showErrorMessage(
"Unable to load SQLFluff due to configuration issue. Try linting an sql file to see more details."
);
} else {
vscode.window.showErrorMessage([message, detail].join("\n"));
}
}

resolve({
// 0 = all good, 1 = format passed but contains unfixable linting violations, 65 = lint passed but found errors
succeeded: succeeded,
Expand Down Expand Up @@ -133,7 +145,7 @@ export default class SQLFluff {
const dbtInterface = new DbtInterface(
shouldUseStdin ? options.fileContents : undefined,
options.workspacePath ?? options.filePath,
Configuration.config(),
Configuration.config()
);

Utilities.outputChannel.appendLine("\n--------------------Executing Command--------------------\n");
Expand All @@ -157,19 +169,32 @@ export default class SQLFluff {
},
];

Utilities.outputChannel.appendLine("Raw dbt-omsosis /lint output:");
Utilities.outputChannel.appendLine("Raw dbt-core-interface /lint output:");
Utilities.appendHyphenatedLine();
Utilities.outputChannel.appendLine(JSON.stringify(response, undefined, 2));
Utilities.appendHyphenatedLine();

return new Promise<CommandOutput>((resolve) => {
return new Promise<CommandOutput>(async (resolve) => {
const code = response?.error?.code ?? 0;
const succeeded = code === 0;
if (!succeeded && !Configuration.suppressNotifications()) {
const succeeded = code === 0 && !response?.error;
if (!succeeded && !Configuration.suppressNotifications() && !this.shownDbtInterfacePopup) {
const message = response?.error?.message ?? "DBT-Interface linting error.";
const detail = response?.error?.data?.error ?? "";

vscode.window.showErrorMessage([message, detail].join("\n"));
if (code === DbtInterfaceErrorCode.CompileSqlFailure) {
this.shownDbtInterfacePopup = true;
const runDbt = "Debug by running dbt Compile";
const chosen = await vscode.window.showErrorMessage(message, runDbt);
if (chosen === runDbt) {
await vscode.commands.executeCommand("dbtPowerUser.dbtCompile");
}
} else if (code === DbtInterfaceErrorCode.UnlintableUnfixable) {
vscode.window.showErrorMessage(
"Unable to load SQLFluff due to configuration issue. Try linting an sql file to see more details."
);
} else {
vscode.window.showErrorMessage([message, detail].join("\n"));
}
}

resolve({
Expand All @@ -185,7 +210,7 @@ export default class SQLFluff {
normalizedWorkingDirectory: string | undefined,
shouldUseStdin: boolean,
options: CommandOptions | undefined,
command: CommandType | undefined,
command: CommandType | undefined
): Promise<CommandOutput> {
return new Promise<CommandOutput>((resolve) => {
const stdoutLint = new LineDecoder();
Expand Down
Loading