Skip to content
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
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

All notable changes to Simple DB are documented in this file.

## 0.1.6 - 2026-08-08

### Added

- The complete connection and query workflow to the **Simple DB** right-click submenu of regular SQL files: create/select/connect/disconnect/test/edit/delete/refresh connections, create queries, run statement/selection/script, cancel, and transaction controls.
- **Go to Package Specification** and **Go to Package Body** for explicit Oracle package navigation.

### Changed

- Connection commands launched from a SQL editor now use the connection attached to that file. If the file has no connection yet, Simple DB opens the same cancellable connection picker first.
- The Command Palette still exposes only **Simple DB: Open Configuration**.

## 0.1.5 - 2026-08-08

### Added
Expand Down
24 changes: 19 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Simple DB

Simple DB `0.1.5` is a Visual Studio Code extension written entirely in JavaScript for working with **SQLite, PostgreSQL, MySQL, SQL Server, and Oracle** through a single interface.
Simple DB `0.1.6` is a Visual Studio Code extension written entirely in JavaScript for working with **SQLite, PostgreSQL, MySQL, SQL Server, and Oracle** through a single interface.

The extension opens regular VS Code SQL documents and loads `src/extension.js` directly: there is no TypeScript, `tsconfig.json`, `dist` folder, or compilation step.

Expand Down Expand Up @@ -42,7 +42,7 @@ The extension opens regular VS Code SQL documents and loads `src/extension.js` d
| SQL Server | `mssql` | databases, schemas, tables, views, procedures/functions, indexes, triggers, sequences, types, synonyms, `GO` |
| Oracle | `oracledb` Thin | schemas, tables, views/materialized views, procedures/functions, packages, indexes, triggers, sequences, types, synonyms, PL/SQL |

Oracle uses the default `node-oracledb` Thin mode, so normal connections do not require Oracle Client to be installed. Simple DB `0.1.5` uses SQL authentication with a username and password for SQL Server.
Oracle uses the default `node-oracledb` Thin mode, so normal connections do not require Oracle Client to be installed. Simple DB `0.1.6` uses SQL authentication with a username and password for SQL Server.

## No imposed row limit by default

Expand Down Expand Up @@ -143,20 +143,34 @@ The `id` is generated and managed by Simple DB. Do not change it. Use **Simple D

### Editor context menu

Right-clicking inside an editor now shows a native **Simple DB** submenu with the main actions:
Right-clicking inside any regular SQL editor shows a native **Simple DB** submenu with the complete working set:

- Open Configuration
- Refresh Connections
- Open Connections Folder
- Select / Change Connection...
- Create Connection
- Connect / Disconnect
- Test Connection
- Open Connection JSON
- Set Password
- Delete Connection
- New Query
- Run Statement (`Ctrl+Enter`)
- Execute Selection
- Run Script (`F5`)
- Cancel Query
- Begin Transaction / Commit / Rollback
- Go to Definition (`F12`)
- Go to Declaration
- Go to Package Specification
- Go to Package Body

**Open Configuration** opens the same Simple DB Activity Bar view as clicking the Simple DB icon, where all configured database connections and their explorer actions are available. The Command Palette intentionally exposes only **Simple DB: Open Configuration**; SQL-file actions stay in this right-click submenu, their keyboard shortcuts, and the SQL editor controls.
**Open Configuration** opens the same Simple DB Activity Bar view as clicking the Simple DB icon, where all configured database connections and their explorer actions are available. The Command Palette intentionally exposes only **Simple DB: Open Configuration**; SQL-file actions stay in this right-click submenu, their keyboard shortcuts, and the SQL editor controls. Connection actions invoked from a SQL file operate on the connection attached to that file. If no connection is attached yet, Simple DB opens the connection picker first.

The lower-right status bar shows the profile currently attached to the SQL file. **Select / Change Connection...** marks that profile in the picker and lets the file switch to another one. If there are no profiles yet, **Create New Connection...** is available directly in the picker. The picker and connection-creation prompts can be cancelled with **Cancel / Close**, `Esc`, or by clicking outside. Cancelling nested connection creation closes the selection flow instead of reopening it.

Navigation resolves against the connection attached to the SQL file and opens database-provided source/DDL in a read-only virtual SQL document. Oracle package **Go to Declaration** targets the package specification while **Go to Definition** targets the package body. When an overload can be identified from the call arguments, Simple DB selects it; when several overloads remain valid, it presents all valid locations instead of guessing. `alias.column` references are resolved back to their underlying table/view column, Oracle and SQL Server synonyms are followed to the target object when it is local/resolvable, and navigation can continue from one opened database definition into another. If catalog/source permissions are insufficient, Simple DB reports that explicitly.
Navigation resolves against the connection attached to the SQL file and opens database-provided source/DDL in a read-only virtual SQL document. Oracle package **Go to Declaration** targets the package specification while **Go to Definition** targets the package body. **Go to Package Specification** and **Go to Package Body** provide explicit package-only navigation when the symbol under the cursor resolves to an Oracle package or package member. When an overload can be identified from the call arguments, Simple DB selects it; when several overloads remain valid, it presents all valid locations instead of guessing. `alias.column` references are resolved back to their underlying table/view column, Oracle and SQL Server synonyms are followed to the target object when it is local/resolvable, and navigation can continue from one opened database definition into another. If catalog/source permissions are insufficient, Simple DB reports that explicitly.

### SQLite note

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

113 changes: 108 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "simple-db-suzdalenko",
"displayName": "Simple DB - SQL Client for SQLite, MySQL, PostgreSQL, SQL Server & Oracle",
"description": "SQL client and database editor for SQLite, MySQL, PostgreSQL, SQL Server (MSSQL) and Oracle. Browse database objects, run queries, manage DDL and export results.",
"version": "0.1.5",
"version": "0.1.6",
"publisher": "suzdalenko-dev",
"license": "MIT",
"icon": "resources/simple-db-marketplace.png",
Expand Down Expand Up @@ -160,6 +160,16 @@
"title": "Go to Declaration",
"category": "Simple DB"
},
{
"command": "simpleDb.goToPackageSpecification",
"title": "Go to Package Specification",
"category": "Simple DB"
},
{
"command": "simpleDb.goToPackageBody",
"title": "Go to Package Body",
"category": "Simple DB"
},
{
"command": "simpleDb.cancelQuery",
"title": "Cancel Query",
Expand Down Expand Up @@ -323,6 +333,14 @@
"command": "simpleDb.goToDeclaration",
"when": "false"
},
{
"command": "simpleDb.goToPackageSpecification",
"when": "false"
},
{
"command": "simpleDb.goToPackageBody",
"when": "false"
},
{
"command": "simpleDb.cancelQuery",
"when": "false"
Expand Down Expand Up @@ -493,30 +511,115 @@
"when": "editorLangId == sql",
"group": "1_configuration@1"
},
{
"command": "simpleDb.refreshConnections",
"when": "editorLangId == sql && resourceScheme != simple-db-definition",
"group": "1_configuration@2"
},
{
"command": "simpleDb.openConnectionsFolder",
"when": "editorLangId == sql && resourceScheme != simple-db-definition",
"group": "1_configuration@3"
},
{
"command": "simpleDb.changeEditorConnection",
"when": "editorLangId == sql && resourceScheme != simple-db-definition",
"group": "2_connection@1"
},
{
"command": "simpleDb.executeCurrent",
"command": "simpleDb.addConnection",
"when": "editorLangId == sql && resourceScheme != simple-db-definition",
"group": "2_connection@2"
},
{
"command": "simpleDb.connect",
"when": "editorLangId == sql && resourceScheme != simple-db-definition",
"group": "2_connection@3"
},
{
"command": "simpleDb.disconnect",
"when": "editorLangId == sql && resourceScheme != simple-db-definition",
"group": "2_connection@4"
},
{
"command": "simpleDb.testConnection",
"when": "editorLangId == sql && resourceScheme != simple-db-definition",
"group": "2_connection@5"
},
{
"command": "simpleDb.editConnection",
"when": "editorLangId == sql && resourceScheme != simple-db-definition",
"group": "2_connection@6"
},
{
"command": "simpleDb.setPassword",
"when": "editorLangId == sql && resourceScheme != simple-db-definition",
"group": "2_connection@7"
},
{
"command": "simpleDb.deleteConnection",
"when": "editorLangId == sql && resourceScheme != simple-db-definition",
"group": "2_connection@8"
},
{
"command": "simpleDb.newQuery",
"when": "editorLangId == sql && resourceScheme != simple-db-definition",
"group": "3_run@1"
},
{
"command": "simpleDb.executeDocument",
"command": "simpleDb.executeCurrent",
"when": "editorLangId == sql && resourceScheme != simple-db-definition",
"group": "3_run@2"
},
{
"command": "simpleDb.executeSelection",
"when": "editorLangId == sql && resourceScheme != simple-db-definition",
"group": "3_run@3"
},
{
"command": "simpleDb.executeDocument",
"when": "editorLangId == sql && resourceScheme != simple-db-definition",
"group": "3_run@4"
},
{
"command": "simpleDb.cancelQuery",
"when": "editorLangId == sql && resourceScheme != simple-db-definition",
"group": "3_run@5"
},
{
"command": "simpleDb.beginTransaction",
"when": "editorLangId == sql && resourceScheme != simple-db-definition",
"group": "4_transaction@1"
},
{
"command": "simpleDb.commit",
"when": "editorLangId == sql && resourceScheme != simple-db-definition",
"group": "4_transaction@2"
},
{
"command": "simpleDb.rollback",
"when": "editorLangId == sql && resourceScheme != simple-db-definition",
"group": "4_transaction@3"
},
{
"command": "simpleDb.goToDefinition",
"when": "editorLangId == sql",
"group": "4_navigation@1"
"group": "5_navigation@1"
},
{
"command": "simpleDb.goToDeclaration",
"when": "editorLangId == sql",
"group": "4_navigation@2"
"group": "5_navigation@2"
},
{
"command": "simpleDb.goToPackageSpecification",
"when": "editorLangId == sql",
"group": "5_navigation@3"
},
{
"command": "simpleDb.goToPackageBody",
"when": "editorLangId == sql",
"group": "5_navigation@4"
}
]
},
Expand Down
53 changes: 41 additions & 12 deletions src/extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,23 @@ async function pickProfile(connectionStore, title = 'Simple DB — Select Connec
return pick && !pick.cancel ? pick.profile : null;
}

async function profileForCommand(connectionStore, editorSessionManager, node) {
const nodeProfile = profileForNode(connectionStore, node);
if (nodeProfile) return nodeProfile;

const editor = vscode.window.activeTextEditor;
if (
editor?.document?.languageId === 'sql' &&
editor.document.uri.scheme !== DEFINITION_SCHEME
) {
const session = await editorSessionManager.ensureSession(editor.document);
if (!session) return null;
return connectionStore.get(session.profileId) || null;
}

return pickProfile(connectionStore);
}

function databaseContext(profile, node) {
return (
node?.database ||
Expand Down Expand Up @@ -235,17 +252,17 @@ async function activate(context) {
});

registerCommand(context, 'simpleDb.connect', async (node) => {
const profile = profileForNode(connectionStore, node);
if (!profile) throw new Error('Connection not found.');
const profile = await profileForCommand(connectionStore, editorSessionManager, node);
if (!profile) return;
const adapter = await connectionManager.connect(profile.id);
vscode.window.showInformationMessage(
`Simple DB: connected to ${profile.name} · ${adapter.serverVersion}`,
);
});

registerCommand(context, 'simpleDb.disconnect', async (node) => {
const profile = profileForNode(connectionStore, node);
if (!profile) throw new Error('Connection not found.');
const profile = await profileForCommand(connectionStore, editorSessionManager, node);
if (!profile) return;
const transactionCount = connectionManager.transactionCount(profile.id);
const executionCount = connectionManager.executionCount(profile.id);
if (transactionCount > 0 || executionCount > 0) {
Expand All @@ -264,17 +281,17 @@ async function activate(context) {
});

registerCommand(context, 'simpleDb.testConnection', async (node) => {
const profile = profileForNode(connectionStore, node) || (await pickProfile(connectionStore));
if (!profile) throw new Error('Connection not found.');
const profile = await profileForCommand(connectionStore, editorSessionManager, node);
if (!profile) return;
const result = await connectionManager.testConnection(profile.id);
vscode.window.showInformationMessage(
`Simple DB: ${profile.name} responded in ${result.elapsedMs} ms · ${result.serverVersion}`,
);
});

registerCommand(context, 'simpleDb.editConnection', async (node) => {
const profile = profileForNode(connectionStore, node);
if (!profile) throw new Error('Connection not found.');
const profile = await profileForCommand(connectionStore, editorSessionManager, node);
if (!profile) return;
if (connectionManager.isConnected(profile.id)) {
const transactions = connectionManager.transactionCount(profile.id);
const executions = connectionManager.executionCount(profile.id);
Expand All @@ -298,7 +315,7 @@ async function activate(context) {
});

registerCommand(context, 'simpleDb.setPassword', async (node) => {
const profile = profileForNode(connectionStore, node) || (await pickProfile(connectionStore));
const profile = await profileForCommand(connectionStore, editorSessionManager, node);
if (!profile) return;
if (profile.engine === 'sqlite') {
vscode.window.showInformationMessage('Simple DB: SQLite connections do not use a password.');
Expand All @@ -320,8 +337,8 @@ async function activate(context) {
});

registerCommand(context, 'simpleDb.deleteConnection', async (node) => {
const profile = profileForNode(connectionStore, node);
if (!profile) throw new Error('Connection not found.');
const profile = await profileForCommand(connectionStore, editorSessionManager, node);
if (!profile) return;
const transactions = connectionManager.transactionCount(profile.id);
const executions = connectionManager.executionCount(profile.id);
const warning = transactions > 0 || executions > 0
Expand All @@ -341,7 +358,7 @@ async function activate(context) {
});

registerCommand(context, 'simpleDb.newQuery', async (node) => {
const profile = profileForNode(connectionStore, node) || (await pickProfile(connectionStore));
const profile = await profileForCommand(connectionStore, editorSessionManager, node);
if (!profile) return;
const database = databaseContext(profile, node);
const schema = schemaContext(profile, node, database);
Expand All @@ -358,6 +375,18 @@ async function activate(context) {
registerCommand(context, 'simpleDb.goToDeclaration', () =>
sqlNavigationProvider.openFromActiveEditor('declaration'),
);
registerCommand(context, 'simpleDb.goToPackageSpecification', () =>
sqlNavigationProvider.openFromActiveEditor('declaration', {
objectType: 'package',
label: 'package specification',
}),
);
registerCommand(context, 'simpleDb.goToPackageBody', () =>
sqlNavigationProvider.openFromActiveEditor('definition', {
objectType: 'package',
label: 'package body',
}),
);

registerCommand(context, 'simpleDb.executeCurrent', () => queryRunner.run('current'));
registerCommand(context, 'simpleDb.executeSelection', () =>
Expand Down
Loading
Loading