mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-02 09:35:40 -05:00
Add option for using generic SQL queries to filter EditData rows via a query editor pane. (#1329)
This commit is contained in:
@@ -33,6 +33,8 @@ import { QueryPlanEditor } from 'sql/parts/queryPlan/queryPlanEditor';
|
||||
import { QueryPlanInput } from 'sql/parts/queryPlan/queryPlanInput';
|
||||
import * as Constants from 'sql/parts/query/common/constants';
|
||||
import { localize } from 'vs/nls';
|
||||
import { EditDataResultsEditor } from 'sql/parts/editData/editor/editDataResultsEditor';
|
||||
import { EditDataResultsInput } from 'sql/parts/editData/common/editDataResultsInput';
|
||||
|
||||
const gridCommandsWeightBonus = 100; // give our commands a little bit more weight over other default list/tree commands
|
||||
|
||||
@@ -81,6 +83,16 @@ const editDataEditorDescriptor = new EditorDescriptor(
|
||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors)
|
||||
.registerEditor(editDataEditorDescriptor, [new SyncDescriptor(EditDataInput)]);
|
||||
|
||||
// Editor
|
||||
const editDataResultsEditorDescriptor = new EditorDescriptor(
|
||||
EditDataResultsEditor,
|
||||
EditDataResultsEditor.ID,
|
||||
'EditDataResults'
|
||||
);
|
||||
|
||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors)
|
||||
.registerEditor(editDataResultsEditorDescriptor, [new SyncDescriptor(EditDataResultsInput)]);
|
||||
|
||||
let actionRegistry = <IWorkbenchActionRegistry>Registry.as(Extensions.WorkbenchActions);
|
||||
|
||||
// Query Actions
|
||||
|
||||
@@ -30,7 +30,7 @@ export interface IQueryEditorService {
|
||||
newQueryPlanEditor(xmlShowPlan: string): Promise<any>;
|
||||
|
||||
// Creates new edit data session
|
||||
newEditDataEditor(schemaName: string, tableName: string): Promise<IConnectableInput>;
|
||||
newEditDataEditor(schemaName: string, tableName: string, queryString: string): Promise<IConnectableInput>;
|
||||
|
||||
// Clears any QueryEditor data for the given URI held by this service
|
||||
onQueryInputClosed(uri: string): void;
|
||||
|
||||
@@ -43,7 +43,7 @@ export interface IQueryManagementService {
|
||||
onEditSessionReady(ownerUri: string, success: boolean, message: string): void;
|
||||
|
||||
// Edit Data Functions
|
||||
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): Thenable<void>;
|
||||
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number, queryString: string): Thenable<void>;
|
||||
disposeEdit(ownerUri: string): Thenable<void>;
|
||||
updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<sqlops.EditUpdateCellResult>;
|
||||
commitEdit(ownerUri): Thenable<void>;
|
||||
@@ -68,7 +68,7 @@ export interface IQueryRequestHandler {
|
||||
saveResults(requestParams: sqlops.SaveResultsRequestParams): Thenable<sqlops.SaveResultRequestResult>;
|
||||
|
||||
// Edit Data actions
|
||||
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): Thenable<void>;
|
||||
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number, queryString: string): Thenable<void>;
|
||||
disposeEdit(ownerUri: string): Thenable<void>;
|
||||
updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<sqlops.EditUpdateCellResult>;
|
||||
commitEdit(ownerUri): Thenable<void>;
|
||||
@@ -244,9 +244,9 @@ export class QueryManagementService implements IQueryManagementService {
|
||||
}
|
||||
|
||||
// Edit Data Functions
|
||||
public initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): Thenable<void> {
|
||||
public initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number, queryString: string): Thenable<void> {
|
||||
return this._runAction(ownerUri, (runner) => {
|
||||
return runner.initializeEdit(ownerUri, schemaName, objectName, objectType, rowLimit);
|
||||
return runner.initializeEdit(ownerUri, schemaName, objectName, objectType, rowLimit, queryString);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import { IQueryModelService } from 'sql/parts/query/execution/queryModel';
|
||||
import * as WorkbenchUtils from 'sql/workbench/common/sqlWorkbenchUtils';
|
||||
import * as Constants from 'sql/parts/query/common/constants';
|
||||
import * as ConnectionConstants from 'sql/parts/connection/common/constants';
|
||||
import { EditDataEditor } from 'sql/parts/editData/editor/editDataEditor';
|
||||
|
||||
const singleQuote = '\'';
|
||||
|
||||
@@ -98,8 +99,8 @@ export class RunQueryKeyboardAction extends Action {
|
||||
|
||||
public run(): TPromise<void> {
|
||||
let editor = this._editorService.getActiveEditor();
|
||||
if (editor && editor instanceof QueryEditor) {
|
||||
let queryEditor: QueryEditor = editor;
|
||||
if (editor && (editor instanceof QueryEditor || editor instanceof EditDataEditor)) {
|
||||
let queryEditor: QueryEditor | EditDataEditor = editor;
|
||||
queryEditor.runQuery();
|
||||
}
|
||||
return TPromise.as(null);
|
||||
@@ -174,8 +175,8 @@ export class CancelQueryKeyboardAction extends Action {
|
||||
|
||||
public run(): TPromise<void> {
|
||||
let editor = this._editorService.getActiveEditor();
|
||||
if (editor && editor instanceof QueryEditor) {
|
||||
let queryEditor: QueryEditor = editor;
|
||||
if (editor && (editor instanceof QueryEditor || editor instanceof EditDataEditor)) {
|
||||
let queryEditor: QueryEditor | EditDataEditor = editor;
|
||||
queryEditor.cancelQuery();
|
||||
}
|
||||
return TPromise.as(null);
|
||||
|
||||
@@ -57,7 +57,7 @@ export interface IQueryModelService {
|
||||
|
||||
|
||||
// Edit Data Functions
|
||||
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): void;
|
||||
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number, queryString: string): void;
|
||||
disposeEdit(ownerUri: string): Thenable<void>;
|
||||
updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<EditUpdateCellResult>;
|
||||
commitEdit(ownerUri): Thenable<void>;
|
||||
|
||||
@@ -352,7 +352,7 @@ export class QueryModelService implements IQueryModelService {
|
||||
}
|
||||
|
||||
// EDIT DATA METHODS /////////////////////////////////////////////////////
|
||||
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): void {
|
||||
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number, queryString: string): void {
|
||||
// Reuse existing query runner if it exists
|
||||
let queryRunner: QueryRunner;
|
||||
let info: QueryInfo;
|
||||
@@ -368,6 +368,8 @@ export class QueryModelService implements IQueryModelService {
|
||||
|
||||
queryRunner = existingRunner;
|
||||
} else {
|
||||
info = new QueryInfo();
|
||||
|
||||
// We do not have a query runner for this editor, so create a new one
|
||||
// and map it to the results uri
|
||||
queryRunner = this._instantiationService.createInstance(QueryRunner, ownerUri, ownerUri);
|
||||
@@ -376,15 +378,21 @@ export class QueryModelService implements IQueryModelService {
|
||||
});
|
||||
queryRunner.addListener(QREvents.BATCH_START, batch => {
|
||||
let link = undefined;
|
||||
let messageText = LocalizedConstants.runQueryBatchStartMessage;
|
||||
if (batch.selection) {
|
||||
link = {
|
||||
text: strings.format(LocalizedConstants.runQueryBatchStartLine, batch.selection.startLine + 1),
|
||||
uri: ''
|
||||
};
|
||||
if (info.selectionSnippet) {
|
||||
// This indicates it's a query string. Do not include line information since it'll be inaccurate, but show some of the
|
||||
// executed query text
|
||||
messageText = nls.localize('runQueryStringBatchStartMessage', 'Started executing query "{0}"', info.selectionSnippet);
|
||||
} else {
|
||||
link = {
|
||||
text: strings.format(LocalizedConstants.runQueryBatchStartLine, batch.selection.startLine + 1)
|
||||
};
|
||||
}
|
||||
}
|
||||
let message = {
|
||||
message: LocalizedConstants.runQueryBatchStartMessage,
|
||||
batchId: undefined,
|
||||
message: messageText,
|
||||
batchId: batch.id,
|
||||
isError: false,
|
||||
time: new Date().toLocaleTimeString(),
|
||||
link: link
|
||||
@@ -407,13 +415,20 @@ export class QueryModelService implements IQueryModelService {
|
||||
this._fireQueryEvent(e.ownerUri, 'editSessionReady');
|
||||
});
|
||||
|
||||
info = new QueryInfo();
|
||||
info.queryRunner = queryRunner;
|
||||
info.dataService = this._instantiationService.createInstance(DataService, ownerUri);
|
||||
this._queryInfoMap.set(ownerUri, info);
|
||||
}
|
||||
|
||||
queryRunner.initializeEdit(ownerUri, schemaName, objectName, objectType, rowLimit);
|
||||
if (queryString) {
|
||||
if (queryString.length < selectionSnippetMaxLen) {
|
||||
info.selectionSnippet = queryString;
|
||||
} else {
|
||||
info.selectionSnippet = queryString.substring(0, selectionSnippetMaxLen - 3) + '...';
|
||||
}
|
||||
}
|
||||
|
||||
queryRunner.initializeEdit(ownerUri, schemaName, objectName, objectType, rowLimit, queryString);
|
||||
}
|
||||
|
||||
public cancelInitializeEdit(input: QueryRunner | string): void {
|
||||
|
||||
@@ -300,13 +300,13 @@ export default class QueryRunner {
|
||||
/*
|
||||
* Handle a session ready event for Edit Data
|
||||
*/
|
||||
public initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): Thenable<void> {
|
||||
public initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number, queryString: string): Thenable<void> {
|
||||
// Update internal state to show that we're executing the query
|
||||
this._isExecuting = true;
|
||||
this._totalElapsedMilliseconds = 0;
|
||||
// TODO issue #228 add statusview callbacks here
|
||||
|
||||
return this._queryManagementService.initializeEdit(ownerUri, schemaName, objectName, objectType, rowLimit).then(result => {
|
||||
return this._queryManagementService.initializeEdit(ownerUri, schemaName, objectName, objectType, rowLimit, queryString).then(result => {
|
||||
// The query has started, so lets fire up the result pane
|
||||
this._eventEmitter.emit(EventType.START);
|
||||
this._queryManagementService.registerRunner(this, ownerUri);
|
||||
|
||||
@@ -29,6 +29,7 @@ import paths = require('vs/base/common/paths');
|
||||
import { isLinux } from 'vs/base/common/platform';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { EditDataResultsInput } from 'sql/parts/editData/common/editDataResultsInput';
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
@@ -120,7 +121,7 @@ export class QueryEditorService implements IQueryEditorService {
|
||||
/**
|
||||
* Creates new edit data session
|
||||
*/
|
||||
public newEditDataEditor(schemaName: string, tableName: string): Promise<IConnectableInput> {
|
||||
public newEditDataEditor(schemaName: string, tableName: string, sqlContent: string): Promise<IConnectableInput> {
|
||||
|
||||
return new Promise<IConnectableInput>((resolve, reject) => {
|
||||
try {
|
||||
@@ -129,8 +130,17 @@ export class QueryEditorService implements IQueryEditorService {
|
||||
let filePath = this.createEditDataFileName(objectName);
|
||||
let docUri: URI = URI.from({ scheme: Schemas.untitled, path: filePath });
|
||||
|
||||
// Create a sql document pane with accoutrements
|
||||
const fileInput = this._untitledEditorService.createOrGet(docUri, 'sql');
|
||||
fileInput.resolve().then(m => {
|
||||
if (sqlContent) {
|
||||
m.textEditorModel.setValue(sqlContent);
|
||||
}
|
||||
});
|
||||
|
||||
// Create an EditDataInput for editing
|
||||
let editDataInput: EditDataInput = this._instantiationService.createInstance(EditDataInput, docUri, schemaName, tableName);
|
||||
const resultsInput: EditDataResultsInput = this._instantiationService.createInstance(EditDataResultsInput, docUri.toString());
|
||||
let editDataInput: EditDataInput = this._instantiationService.createInstance(EditDataInput, docUri, schemaName, tableName, fileInput, sqlContent, resultsInput);
|
||||
|
||||
this._editorService.openEditor(editDataInput, { pinned: true })
|
||||
.then((editor) => {
|
||||
@@ -212,7 +222,7 @@ export class QueryEditorService implements IQueryEditorService {
|
||||
}
|
||||
|
||||
let uri: URI = QueryEditorService._getEditorChangeUri(editor.input, changingToSql);
|
||||
if(uri.scheme === Schemas.untitled && editor.input instanceof QueryInput)
|
||||
if(uri.scheme === Schemas.untitled && (editor.input instanceof QueryInput || editor.input instanceof EditDataInput))
|
||||
{
|
||||
QueryEditorService.notificationService.notify({
|
||||
severity: Severity.Error,
|
||||
@@ -299,10 +309,8 @@ export class QueryEditorService implements IQueryEditorService {
|
||||
filePath = editDataFileName(counter);
|
||||
}
|
||||
|
||||
// TODO: check if this document name already exists in any open documents tabs
|
||||
let fileNames: string[] = [];
|
||||
this._editorGroupService.getStacksModel().groups.map(group => group.getEditors().map(editor => fileNames.push(editor.getName())));
|
||||
while (fileNames.find(x => x.toUpperCase() === filePath.toUpperCase())) {
|
||||
let untitledEditors = this._untitledEditorService.getAll();
|
||||
while (untitledEditors.find(x => x.getName().toUpperCase() === filePath.toUpperCase())) {
|
||||
counter++;
|
||||
filePath = editDataFileName(counter);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user