plsqlwks 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- plsqlwks-0.1.0/PKG-INFO +269 -0
- plsqlwks-0.1.0/README.md +251 -0
- plsqlwks-0.1.0/plsqlwks/__init__.py +3 -0
- plsqlwks-0.1.0/plsqlwks/__main__.py +5 -0
- plsqlwks-0.1.0/plsqlwks/config/__init__.py +117 -0
- plsqlwks-0.1.0/plsqlwks/config/loader.py +59 -0
- plsqlwks-0.1.0/plsqlwks/config/models.py +50 -0
- plsqlwks-0.1.0/plsqlwks/config/paths.py +96 -0
- plsqlwks-0.1.0/plsqlwks/config/session.py +96 -0
- plsqlwks-0.1.0/plsqlwks/config/settings.py +170 -0
- plsqlwks-0.1.0/plsqlwks/db/__init__.py +201 -0
- plsqlwks-0.1.0/plsqlwks/db/editing.py +478 -0
- plsqlwks-0.1.0/plsqlwks/db/execution.py +317 -0
- plsqlwks-0.1.0/plsqlwks/db/explain.py +164 -0
- plsqlwks-0.1.0/plsqlwks/db/health.py +13 -0
- plsqlwks-0.1.0/plsqlwks/db/metadata.py +158 -0
- plsqlwks-0.1.0/plsqlwks/db/models.py +265 -0
- plsqlwks-0.1.0/plsqlwks/db/session.py +74 -0
- plsqlwks-0.1.0/plsqlwks/db/sql_analysis.py +251 -0
- plsqlwks-0.1.0/plsqlwks/db/transactions.py +359 -0
- plsqlwks-0.1.0/plsqlwks/sqlbinds.py +163 -0
- plsqlwks-0.1.0/plsqlwks/sqlsplit.py +274 -0
- plsqlwks-0.1.0/plsqlwks/ui/__init__.py +496 -0
- plsqlwks-0.1.0/plsqlwks/ui/app.py +130 -0
- plsqlwks-0.1.0/plsqlwks/ui/app_db.py +654 -0
- plsqlwks-0.1.0/plsqlwks/ui/app_editor.py +390 -0
- plsqlwks-0.1.0/plsqlwks/ui/app_files.py +471 -0
- plsqlwks-0.1.0/plsqlwks/ui/app_input.py +554 -0
- plsqlwks-0.1.0/plsqlwks/ui/app_render.py +592 -0
- plsqlwks-0.1.0/plsqlwks/ui/app_results.py +507 -0
- plsqlwks-0.1.0/plsqlwks/ui/app_tabs_browser.py +305 -0
- plsqlwks-0.1.0/plsqlwks/ui/browser.py +116 -0
- plsqlwks-0.1.0/plsqlwks/ui/buffer.py +472 -0
- plsqlwks-0.1.0/plsqlwks/ui/clipboard.py +111 -0
- plsqlwks-0.1.0/plsqlwks/ui/commands.py +78 -0
- plsqlwks-0.1.0/plsqlwks/ui/completion.py +216 -0
- plsqlwks-0.1.0/plsqlwks/ui/constants.py +782 -0
- plsqlwks-0.1.0/plsqlwks/ui/display.py +125 -0
- plsqlwks-0.1.0/plsqlwks/ui/errors.py +281 -0
- plsqlwks-0.1.0/plsqlwks/ui/help.py +128 -0
- plsqlwks-0.1.0/plsqlwks/ui/keys.py +268 -0
- plsqlwks-0.1.0/plsqlwks/ui/menu.py +142 -0
- plsqlwks-0.1.0/plsqlwks/ui/results.py +485 -0
- plsqlwks-0.1.0/plsqlwks/ui/sql.py +158 -0
- plsqlwks-0.1.0/plsqlwks/ui/state.py +260 -0
- plsqlwks-0.1.0/plsqlwks/ui/syntax.py +526 -0
- plsqlwks-0.1.0/plsqlwks/workspace.py +46 -0
- plsqlwks-0.1.0/plsqlwks.egg-info/PKG-INFO +269 -0
- plsqlwks-0.1.0/plsqlwks.egg-info/SOURCES.txt +64 -0
- plsqlwks-0.1.0/plsqlwks.egg-info/dependency_links.txt +1 -0
- plsqlwks-0.1.0/plsqlwks.egg-info/entry_points.txt +2 -0
- plsqlwks-0.1.0/plsqlwks.egg-info/requires.txt +9 -0
- plsqlwks-0.1.0/plsqlwks.egg-info/top_level.txt +1 -0
- plsqlwks-0.1.0/pyproject.toml +78 -0
- plsqlwks-0.1.0/setup.cfg +4 -0
- plsqlwks-0.1.0/tests/test_config_workspace.py +704 -0
- plsqlwks-0.1.0/tests/test_db_editing.py +692 -0
- plsqlwks-0.1.0/tests/test_db_helpers.py +1563 -0
- plsqlwks-0.1.0/tests/test_oracle_integration.py +324 -0
- plsqlwks-0.1.0/tests/test_packaging.py +212 -0
- plsqlwks-0.1.0/tests/test_pty_keys.py +101 -0
- plsqlwks-0.1.0/tests/test_rchar.py +14 -0
- plsqlwks-0.1.0/tests/test_sqlbinds.py +133 -0
- plsqlwks-0.1.0/tests/test_sqlsplit.py +330 -0
- plsqlwks-0.1.0/tests/test_ui_flows.py +2713 -0
- plsqlwks-0.1.0/tests/test_ui_keys.py +4258 -0
plsqlwks-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: plsqlwks
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: An ncurses SQL and PL/SQL workspace for Oracle databases.
|
|
5
|
+
Classifier: Programming Language :: Python :: 3
|
|
6
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
7
|
+
Classifier: Topic :: Database
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: oracledb>=2.0
|
|
11
|
+
Requires-Dist: platformdirs>=4.0
|
|
12
|
+
Provides-Extra: dev
|
|
13
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
14
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
15
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
16
|
+
Requires-Dist: ruff>=0.8; extra == "dev"
|
|
17
|
+
Requires-Dist: wheel>=0.43; extra == "dev"
|
|
18
|
+
|
|
19
|
+
# plsqlwks
|
|
20
|
+
|
|
21
|
+
An ncurses SQL and PL/SQL workspace for the local Oracle database.
|
|
22
|
+
|
|
23
|
+

|
|
24
|
+
|
|
25
|
+
## Connection
|
|
26
|
+
|
|
27
|
+
The default connection is:
|
|
28
|
+
|
|
29
|
+
- user: `hr`
|
|
30
|
+
- password file: the `orapass` file in the platform user-config directory
|
|
31
|
+
- service: `free` on `127.0.0.1:1521`
|
|
32
|
+
|
|
33
|
+
On Linux, fresh defaults are `~/.config/plsqlwks/orapass` for the password,
|
|
34
|
+
`~/.config/plsqlwks/config.ini` for settings, and `~/.local/share/plsqlwks`
|
|
35
|
+
for the workspace. macOS and Windows use their corresponding user config and
|
|
36
|
+
data directories. An existing `/tmp/orapass` remains a compatibility fallback,
|
|
37
|
+
but the app warns about that legacy location and about POSIX permissions other
|
|
38
|
+
than `0600`.
|
|
39
|
+
|
|
40
|
+
Override the defaults with environment variables:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
export ORACLE_USER=hr
|
|
44
|
+
export ORACLE_PASSWORD_FILE=~/.config/plsqlwks/orapass
|
|
45
|
+
export ORACLE_DSN='127.0.0.1:1521/free'
|
|
46
|
+
export PLSQLWKS_WORKSPACE=/mnt/d/dev/plsqlwks/workspace
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Password files preserve leading and trailing spaces; only final CR/LF line
|
|
50
|
+
endings are removed. On POSIX systems, create the file for the current user and
|
|
51
|
+
protect it with `chmod 600`.
|
|
52
|
+
|
|
53
|
+
## Install
|
|
54
|
+
|
|
55
|
+
For development, install the package in editable mode:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
python3 -m pip install -e '.[dev]'
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
See [RELEASING.md](RELEASING.md) for the quality, build, wheel-smoke, Oracle,
|
|
62
|
+
and tagging checklist used for releases.
|
|
63
|
+
|
|
64
|
+
For a regular local install, use:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
python3 -m pip install .
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Run
|
|
71
|
+
|
|
72
|
+
After installation, start the workspace with:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
plsqlwks
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Select a workspace for one invocation with:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
plsqlwks --workspace /path/to/workspace
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The CLI option takes precedence over `PLSQLWKS_WORKSPACE`. For compatibility, a
|
|
85
|
+
source checkout that already contains a configured `workspace/` continues to
|
|
86
|
+
use it and displays a migration notice; files are never moved automatically.
|
|
87
|
+
|
|
88
|
+
You can also run it directly as a module from the source tree:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
python3 -m plsqlwks
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The app opens a split-screen terminal workspace:
|
|
95
|
+
|
|
96
|
+
- editor on top
|
|
97
|
+
- results/messages below
|
|
98
|
+
- command/status bar at the bottom
|
|
99
|
+
|
|
100
|
+
The terminal UI uses the active UTF-8 locale for keyboard input and display. If a terminal starts in a plain `C` locale, the app falls back to `C.UTF-8` when available.
|
|
101
|
+
|
|
102
|
+
After a successful quit, plsqlwks records the open file-backed tabs, active tab, and cursor positions in the managed `[session.tabs]` section of `config.ini`. Fresh platform-default workspaces use the user-config directory; explicitly selected and legacy workspaces keep `config.ini` inside the workspace for compatibility. On the next start the app tries each saved path independently, silently skips files that are missing or unreadable, and leaves the initial empty tab in place when none can be opened. A saved cursor position that no longer exists in its file starts at the beginning instead. Untitled, template, and generated schema tabs are not persisted because they do not have a file to reopen.
|
|
103
|
+
|
|
104
|
+
## Keys
|
|
105
|
+
|
|
106
|
+
### Global
|
|
107
|
+
|
|
108
|
+
| Key | Action |
|
|
109
|
+
| --- | --- |
|
|
110
|
+
| `Alt-O` | Open the top-left commands menu |
|
|
111
|
+
| `F1` | Help |
|
|
112
|
+
| `F6` | Switch between DBMS_OUTPUT and normal results |
|
|
113
|
+
| `F7` | Cycle fullscreen grid, fullscreen editor, and 2/3 editor + 1/3 grid |
|
|
114
|
+
| `F8` | Toggle result grid / row-detail output |
|
|
115
|
+
| `F9` | Show/focus/hide schema browser |
|
|
116
|
+
| `F12` | Choose autocommit or manual transaction mode |
|
|
117
|
+
| `Ctrl-Up` / `Ctrl-Down` | Scroll the focused pane or visible DBMS_OUTPUT |
|
|
118
|
+
| `Ctrl-W` | Close current file tab |
|
|
119
|
+
| `Ctrl-PageUp` / `Ctrl-PageDown` | Switch file tabs |
|
|
120
|
+
| `Alt-1`..`Alt-9` | Jump to visible file tab |
|
|
121
|
+
| `Ctrl-Q` | Quit |
|
|
122
|
+
| `Ctrl-C` while running | Interrupt the active database operation |
|
|
123
|
+
| `Ctrl-Alt-C` | Commit the current transaction |
|
|
124
|
+
| `Ctrl-Alt-R` | Roll back the current transaction |
|
|
125
|
+
|
|
126
|
+
### Editor
|
|
127
|
+
|
|
128
|
+
| Key | Action |
|
|
129
|
+
| --- | --- |
|
|
130
|
+
| Printable text | Insert text |
|
|
131
|
+
| Arrow keys | Move the cursor |
|
|
132
|
+
| `Shift-Arrow` | Select SQL text |
|
|
133
|
+
| `Home` / `End` | Move to the beginning/end of the current line |
|
|
134
|
+
| `Shift-Home` / `Shift-End` | Select to the beginning/end of the current line |
|
|
135
|
+
| `Ctrl-Home` / `Ctrl-End` | Move to the beginning/end of the editor buffer |
|
|
136
|
+
| `Ctrl-Shift-Home` / `Ctrl-Shift-End` | Select to the beginning/end of the editor buffer |
|
|
137
|
+
| `PageUp` / `PageDown` | Move by page |
|
|
138
|
+
| `Shift-PageUp` / `Shift-PageDown` | Select by page |
|
|
139
|
+
| `Ctrl-Left` / `Ctrl-Right` | Move one word |
|
|
140
|
+
| `Ctrl-Shift-Left` / `Ctrl-Shift-Right` | Select one word |
|
|
141
|
+
| `Backspace` | Delete before the cursor |
|
|
142
|
+
| `Delete` | Delete at the cursor |
|
|
143
|
+
| `Ctrl-Backspace` / `Ctrl-Delete` | Delete the previous/next word |
|
|
144
|
+
| `Enter` | Insert a new line |
|
|
145
|
+
| `Tab` | Focus the result table |
|
|
146
|
+
| `Shift-Tab` | Autocomplete keywords, schema objects, and columns |
|
|
147
|
+
| `F2` / `Ctrl-S` | Save buffer |
|
|
148
|
+
| `F3` / `Ctrl-O` | Open file |
|
|
149
|
+
| `F4` | New template |
|
|
150
|
+
| `F5` / `Ctrl-Enter` / `Alt-X` | Execute selected SQL or current statement |
|
|
151
|
+
| `F11` | Execute selected SQL or whole buffer as a script |
|
|
152
|
+
| `Alt-G` | Generate SELECT, INSERT, or UPDATE with table columns |
|
|
153
|
+
| `Alt-+` | Refresh autocomplete metadata cache |
|
|
154
|
+
| `Alt-R` | Rename current buffer |
|
|
155
|
+
| `Ctrl-T` | New file tab |
|
|
156
|
+
| `Ctrl-R` | Refresh workspace file list |
|
|
157
|
+
| `Ctrl-E` | Explain current statement |
|
|
158
|
+
| `Ctrl-B` | Toggle `-- ` comment on the current line or selected lines |
|
|
159
|
+
| `Ctrl-F` | Find literal text |
|
|
160
|
+
| `Ctrl-G` | Go to line |
|
|
161
|
+
| `Ctrl-N` / `Ctrl-P` | Move to the next / previous search occurrence |
|
|
162
|
+
| `Ctrl-U` | Uppercase selected SQL code |
|
|
163
|
+
| `Ctrl-L` | Lowercase selected SQL code |
|
|
164
|
+
| `Ctrl-C` | Copy selected text |
|
|
165
|
+
| `Ctrl-X` | Cut selected text |
|
|
166
|
+
| `Ctrl-V` | Paste clipboard text |
|
|
167
|
+
| `Ctrl-Z` / `Ctrl-Y` | Undo / redo |
|
|
168
|
+
| `Ctrl+=` | Reconnect |
|
|
169
|
+
|
|
170
|
+
Use `/` on a line by itself after PL/SQL objects or anonymous blocks when running a script.
|
|
171
|
+
Execution and explain errors report the mapped editor line and column, then move the cursor to that location when Oracle provides one.
|
|
172
|
+
When executed or explained SQL contains bind variables such as `:id`, plsqlwks opens a text box for each value and sends the answers as Oracle bind parameters.
|
|
173
|
+
Unquoted bind names are case-insensitive, so `:id` and `:ID` share one prompt and value. Quoted bind names remain case-sensitive.
|
|
174
|
+
Set `[database] remember_bind_values = yes` in the active `config.ini` to prefill future bind prompts with values entered earlier in the same app session.
|
|
175
|
+
|
|
176
|
+
Editor search is literal and case-insensitive. `Ctrl-F` prompts for text and selects the found occurrence; `Ctrl-N` and `Ctrl-P` repeat the last search forward or backward with wraparound.
|
|
177
|
+
|
|
178
|
+
Editor autocomplete is available with `Shift-Tab`. It completes PL/SQL keywords, current-schema object names, and table/view columns from cached or lazily loaded database metadata; multiple matches open a picker. Use `Alt-+` to reload schema-object metadata and clear cached column metadata.
|
|
179
|
+
|
|
180
|
+
Editor syntax and explain-plan colors can be overridden in the active `config.ini` with color names or numeric curses color indexes. Unsupported values fall back to the built-in palette for the current terminal:
|
|
181
|
+
|
|
182
|
+
```ini
|
|
183
|
+
[editor.colors]
|
|
184
|
+
keyword = bright-cyan
|
|
185
|
+
string = green
|
|
186
|
+
number = orange
|
|
187
|
+
comment = blue
|
|
188
|
+
bind = bright-magenta
|
|
189
|
+
operator = white
|
|
190
|
+
|
|
191
|
+
[explain.colors]
|
|
192
|
+
connector = cyan
|
|
193
|
+
operation = bright-yellow
|
|
194
|
+
object = green
|
|
195
|
+
metrics = gray
|
|
196
|
+
text = white
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
The bottom status bar starts with `[ ]` when there is no observed uncommitted work and `[*]` when manual mode has pending changes. Commit and rollback messages include the local timestamp and the tracked row count, for example `Committed transaction, 2026-06-12 10:12:15, 7 row(s) changed`. Direct DML and ROWID grid edits contribute exact row counts; PL/SQL blocks can mark the transaction as pending with an unknown row count. Quitting or switching from manual mode to autocommit while changes are pending asks whether to commit, roll back, or cancel. The selected transaction mode is stored under `[database] autocommit` in the active `config.ini`.
|
|
200
|
+
|
|
201
|
+
Read-only mode is a client-side guardrail that rejects statements which the SQL scanner recognizes as database-writing. Select it with `--read-only`, `--read-write`, or `[database] read_only` in `config.ini`. It is not a security boundary: a function invoked by an otherwise valid `SELECT` can perform work outside the visible statement, including an autonomous transaction. Use an Oracle account with only the required privileges when writes must be prevented by the database. In read-only mode, `Ctrl-E` explains `SELECT` and `WITH` statements by opening a cursor and reading `DBMS_XPLAN.DISPLAY_CURSOR`; direct `EXPLAIN PLAN` remains disabled because it writes to `PLAN_TABLE`.
|
|
202
|
+
|
|
203
|
+
### Results And Explain Plan
|
|
204
|
+
|
|
205
|
+
| Key | Action |
|
|
206
|
+
| --- | --- |
|
|
207
|
+
| `Esc` / `Tab` | Return to the editor |
|
|
208
|
+
| Arrow keys | Move through result-grid cells |
|
|
209
|
+
| `PageUp` / `PageDown` | Move by a visible page in the result grid |
|
|
210
|
+
| `Home` / `End` | Move to the first/last result-grid column |
|
|
211
|
+
| `Ctrl-Home` / `Ctrl-End` | Move to the first/last result-grid row |
|
|
212
|
+
| `F8` | Toggle result grid / row-detail output |
|
|
213
|
+
| `F10` | View the full selected result cell |
|
|
214
|
+
| `Enter` | Edit the selected ROWID-backed result cell when available |
|
|
215
|
+
| `INS` | Prepare a draft insert row for ROWID-backed results |
|
|
216
|
+
| `Ctrl-Alt-C` | Insert the active draft row, or commit the transaction when no draft is active |
|
|
217
|
+
| `Up` / `Down` | Scroll explain-plan lines |
|
|
218
|
+
| `PageUp` / `PageDown` | Scroll explain-plan lines by page |
|
|
219
|
+
| `Home` / `End` | Move to the first/last explain-plan line |
|
|
220
|
+
|
|
221
|
+
When more result rows are available, `PageDown` at the loaded end fetches and appends the next result page. For simple single-table queries that select `ROWID`, press `Enter` on a non-`ROWID` cell to update that table column by rowid. Press `INS` in the grid to prepare a draft row at the top of the grid, edit its cells with `Enter`, use `Ctrl-Alt-C` to insert it, or use `Esc` to cancel it.
|
|
222
|
+
Database null values are displayed and entered as `<NULL>` in editable results. Plain `NULL` is stored as literal text.
|
|
223
|
+
`F7` cycles a grid fullscreen view that starts with the table header on the first terminal line and uses the last line for data, an editor-only fullscreen view, and a split layout with 2/3 editor and 1/3 data grid.
|
|
224
|
+
|
|
225
|
+
### Schema Browser
|
|
226
|
+
|
|
227
|
+
The `F9` schema browser groups tables, views, procedures, functions, packages, triggers, sequences, indexes, and private synonyms from the current schema. Type while the browser is focused to filter object names with a case-insensitive substring match; groups without matches are hidden and matching groups expand automatically without changing their saved expansion state.
|
|
228
|
+
|
|
229
|
+
| Key | Action |
|
|
230
|
+
| --- | --- |
|
|
231
|
+
| Printable text | Filter object names |
|
|
232
|
+
| `Backspace` | Delete the final filter character |
|
|
233
|
+
| `Esc` | Clear a nonempty filter, or return to the editor when the filter is empty |
|
|
234
|
+
| `Up` / `Down` | Move through browser entries |
|
|
235
|
+
| `PageUp` / `PageDown` | Move through browser entries by page |
|
|
236
|
+
| `Enter` | Expand a group or load an object definition |
|
|
237
|
+
| `Space` | Expand/collapse a group when the filter is empty, or add a space to the active filter |
|
|
238
|
+
| `Ctrl-R` | Refresh database objects |
|
|
239
|
+
|
|
240
|
+
### Cell Viewer
|
|
241
|
+
|
|
242
|
+
| Key | Action |
|
|
243
|
+
| --- | --- |
|
|
244
|
+
| `Esc` / `Enter` / `F10` | Close the cell viewer |
|
|
245
|
+
| `Up` / `Down` | Scroll cell text |
|
|
246
|
+
| `PageUp` / `PageDown` | Scroll cell text by page |
|
|
247
|
+
| `Home` / `End` | Move to the first/last cell-viewer line |
|
|
248
|
+
|
|
249
|
+
### Prompts And Pickers
|
|
250
|
+
|
|
251
|
+
| Key | Action |
|
|
252
|
+
| --- | --- |
|
|
253
|
+
| Printable text | Type into prompts or filter picker options |
|
|
254
|
+
| `Backspace` | Delete before the prompt cursor or picker filter |
|
|
255
|
+
| `Enter` | Accept the prompt or selected picker item |
|
|
256
|
+
| `Esc` / `Ctrl-Q` | Cancel the prompt or picker |
|
|
257
|
+
| `Up` / `Down` | Move through picker options |
|
|
258
|
+
| `PageUp` / `PageDown` | Move through picker options by page |
|
|
259
|
+
|
|
260
|
+
## Workspace Layout
|
|
261
|
+
|
|
262
|
+
```text
|
|
263
|
+
workspace/
|
|
264
|
+
sql/ saved SQL files
|
|
265
|
+
plsql/ saved PL/SQL files
|
|
266
|
+
results/ exported query output
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
The first launch creates the workspace folders and starter SQL/PLSQL files.
|
plsqlwks-0.1.0/README.md
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# plsqlwks
|
|
2
|
+
|
|
3
|
+
An ncurses SQL and PL/SQL workspace for the local Oracle database.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## Connection
|
|
8
|
+
|
|
9
|
+
The default connection is:
|
|
10
|
+
|
|
11
|
+
- user: `hr`
|
|
12
|
+
- password file: the `orapass` file in the platform user-config directory
|
|
13
|
+
- service: `free` on `127.0.0.1:1521`
|
|
14
|
+
|
|
15
|
+
On Linux, fresh defaults are `~/.config/plsqlwks/orapass` for the password,
|
|
16
|
+
`~/.config/plsqlwks/config.ini` for settings, and `~/.local/share/plsqlwks`
|
|
17
|
+
for the workspace. macOS and Windows use their corresponding user config and
|
|
18
|
+
data directories. An existing `/tmp/orapass` remains a compatibility fallback,
|
|
19
|
+
but the app warns about that legacy location and about POSIX permissions other
|
|
20
|
+
than `0600`.
|
|
21
|
+
|
|
22
|
+
Override the defaults with environment variables:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
export ORACLE_USER=hr
|
|
26
|
+
export ORACLE_PASSWORD_FILE=~/.config/plsqlwks/orapass
|
|
27
|
+
export ORACLE_DSN='127.0.0.1:1521/free'
|
|
28
|
+
export PLSQLWKS_WORKSPACE=/mnt/d/dev/plsqlwks/workspace
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Password files preserve leading and trailing spaces; only final CR/LF line
|
|
32
|
+
endings are removed. On POSIX systems, create the file for the current user and
|
|
33
|
+
protect it with `chmod 600`.
|
|
34
|
+
|
|
35
|
+
## Install
|
|
36
|
+
|
|
37
|
+
For development, install the package in editable mode:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
python3 -m pip install -e '.[dev]'
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
See [RELEASING.md](RELEASING.md) for the quality, build, wheel-smoke, Oracle,
|
|
44
|
+
and tagging checklist used for releases.
|
|
45
|
+
|
|
46
|
+
For a regular local install, use:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
python3 -m pip install .
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Run
|
|
53
|
+
|
|
54
|
+
After installation, start the workspace with:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
plsqlwks
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Select a workspace for one invocation with:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
plsqlwks --workspace /path/to/workspace
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The CLI option takes precedence over `PLSQLWKS_WORKSPACE`. For compatibility, a
|
|
67
|
+
source checkout that already contains a configured `workspace/` continues to
|
|
68
|
+
use it and displays a migration notice; files are never moved automatically.
|
|
69
|
+
|
|
70
|
+
You can also run it directly as a module from the source tree:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
python3 -m plsqlwks
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The app opens a split-screen terminal workspace:
|
|
77
|
+
|
|
78
|
+
- editor on top
|
|
79
|
+
- results/messages below
|
|
80
|
+
- command/status bar at the bottom
|
|
81
|
+
|
|
82
|
+
The terminal UI uses the active UTF-8 locale for keyboard input and display. If a terminal starts in a plain `C` locale, the app falls back to `C.UTF-8` when available.
|
|
83
|
+
|
|
84
|
+
After a successful quit, plsqlwks records the open file-backed tabs, active tab, and cursor positions in the managed `[session.tabs]` section of `config.ini`. Fresh platform-default workspaces use the user-config directory; explicitly selected and legacy workspaces keep `config.ini` inside the workspace for compatibility. On the next start the app tries each saved path independently, silently skips files that are missing or unreadable, and leaves the initial empty tab in place when none can be opened. A saved cursor position that no longer exists in its file starts at the beginning instead. Untitled, template, and generated schema tabs are not persisted because they do not have a file to reopen.
|
|
85
|
+
|
|
86
|
+
## Keys
|
|
87
|
+
|
|
88
|
+
### Global
|
|
89
|
+
|
|
90
|
+
| Key | Action |
|
|
91
|
+
| --- | --- |
|
|
92
|
+
| `Alt-O` | Open the top-left commands menu |
|
|
93
|
+
| `F1` | Help |
|
|
94
|
+
| `F6` | Switch between DBMS_OUTPUT and normal results |
|
|
95
|
+
| `F7` | Cycle fullscreen grid, fullscreen editor, and 2/3 editor + 1/3 grid |
|
|
96
|
+
| `F8` | Toggle result grid / row-detail output |
|
|
97
|
+
| `F9` | Show/focus/hide schema browser |
|
|
98
|
+
| `F12` | Choose autocommit or manual transaction mode |
|
|
99
|
+
| `Ctrl-Up` / `Ctrl-Down` | Scroll the focused pane or visible DBMS_OUTPUT |
|
|
100
|
+
| `Ctrl-W` | Close current file tab |
|
|
101
|
+
| `Ctrl-PageUp` / `Ctrl-PageDown` | Switch file tabs |
|
|
102
|
+
| `Alt-1`..`Alt-9` | Jump to visible file tab |
|
|
103
|
+
| `Ctrl-Q` | Quit |
|
|
104
|
+
| `Ctrl-C` while running | Interrupt the active database operation |
|
|
105
|
+
| `Ctrl-Alt-C` | Commit the current transaction |
|
|
106
|
+
| `Ctrl-Alt-R` | Roll back the current transaction |
|
|
107
|
+
|
|
108
|
+
### Editor
|
|
109
|
+
|
|
110
|
+
| Key | Action |
|
|
111
|
+
| --- | --- |
|
|
112
|
+
| Printable text | Insert text |
|
|
113
|
+
| Arrow keys | Move the cursor |
|
|
114
|
+
| `Shift-Arrow` | Select SQL text |
|
|
115
|
+
| `Home` / `End` | Move to the beginning/end of the current line |
|
|
116
|
+
| `Shift-Home` / `Shift-End` | Select to the beginning/end of the current line |
|
|
117
|
+
| `Ctrl-Home` / `Ctrl-End` | Move to the beginning/end of the editor buffer |
|
|
118
|
+
| `Ctrl-Shift-Home` / `Ctrl-Shift-End` | Select to the beginning/end of the editor buffer |
|
|
119
|
+
| `PageUp` / `PageDown` | Move by page |
|
|
120
|
+
| `Shift-PageUp` / `Shift-PageDown` | Select by page |
|
|
121
|
+
| `Ctrl-Left` / `Ctrl-Right` | Move one word |
|
|
122
|
+
| `Ctrl-Shift-Left` / `Ctrl-Shift-Right` | Select one word |
|
|
123
|
+
| `Backspace` | Delete before the cursor |
|
|
124
|
+
| `Delete` | Delete at the cursor |
|
|
125
|
+
| `Ctrl-Backspace` / `Ctrl-Delete` | Delete the previous/next word |
|
|
126
|
+
| `Enter` | Insert a new line |
|
|
127
|
+
| `Tab` | Focus the result table |
|
|
128
|
+
| `Shift-Tab` | Autocomplete keywords, schema objects, and columns |
|
|
129
|
+
| `F2` / `Ctrl-S` | Save buffer |
|
|
130
|
+
| `F3` / `Ctrl-O` | Open file |
|
|
131
|
+
| `F4` | New template |
|
|
132
|
+
| `F5` / `Ctrl-Enter` / `Alt-X` | Execute selected SQL or current statement |
|
|
133
|
+
| `F11` | Execute selected SQL or whole buffer as a script |
|
|
134
|
+
| `Alt-G` | Generate SELECT, INSERT, or UPDATE with table columns |
|
|
135
|
+
| `Alt-+` | Refresh autocomplete metadata cache |
|
|
136
|
+
| `Alt-R` | Rename current buffer |
|
|
137
|
+
| `Ctrl-T` | New file tab |
|
|
138
|
+
| `Ctrl-R` | Refresh workspace file list |
|
|
139
|
+
| `Ctrl-E` | Explain current statement |
|
|
140
|
+
| `Ctrl-B` | Toggle `-- ` comment on the current line or selected lines |
|
|
141
|
+
| `Ctrl-F` | Find literal text |
|
|
142
|
+
| `Ctrl-G` | Go to line |
|
|
143
|
+
| `Ctrl-N` / `Ctrl-P` | Move to the next / previous search occurrence |
|
|
144
|
+
| `Ctrl-U` | Uppercase selected SQL code |
|
|
145
|
+
| `Ctrl-L` | Lowercase selected SQL code |
|
|
146
|
+
| `Ctrl-C` | Copy selected text |
|
|
147
|
+
| `Ctrl-X` | Cut selected text |
|
|
148
|
+
| `Ctrl-V` | Paste clipboard text |
|
|
149
|
+
| `Ctrl-Z` / `Ctrl-Y` | Undo / redo |
|
|
150
|
+
| `Ctrl+=` | Reconnect |
|
|
151
|
+
|
|
152
|
+
Use `/` on a line by itself after PL/SQL objects or anonymous blocks when running a script.
|
|
153
|
+
Execution and explain errors report the mapped editor line and column, then move the cursor to that location when Oracle provides one.
|
|
154
|
+
When executed or explained SQL contains bind variables such as `:id`, plsqlwks opens a text box for each value and sends the answers as Oracle bind parameters.
|
|
155
|
+
Unquoted bind names are case-insensitive, so `:id` and `:ID` share one prompt and value. Quoted bind names remain case-sensitive.
|
|
156
|
+
Set `[database] remember_bind_values = yes` in the active `config.ini` to prefill future bind prompts with values entered earlier in the same app session.
|
|
157
|
+
|
|
158
|
+
Editor search is literal and case-insensitive. `Ctrl-F` prompts for text and selects the found occurrence; `Ctrl-N` and `Ctrl-P` repeat the last search forward or backward with wraparound.
|
|
159
|
+
|
|
160
|
+
Editor autocomplete is available with `Shift-Tab`. It completes PL/SQL keywords, current-schema object names, and table/view columns from cached or lazily loaded database metadata; multiple matches open a picker. Use `Alt-+` to reload schema-object metadata and clear cached column metadata.
|
|
161
|
+
|
|
162
|
+
Editor syntax and explain-plan colors can be overridden in the active `config.ini` with color names or numeric curses color indexes. Unsupported values fall back to the built-in palette for the current terminal:
|
|
163
|
+
|
|
164
|
+
```ini
|
|
165
|
+
[editor.colors]
|
|
166
|
+
keyword = bright-cyan
|
|
167
|
+
string = green
|
|
168
|
+
number = orange
|
|
169
|
+
comment = blue
|
|
170
|
+
bind = bright-magenta
|
|
171
|
+
operator = white
|
|
172
|
+
|
|
173
|
+
[explain.colors]
|
|
174
|
+
connector = cyan
|
|
175
|
+
operation = bright-yellow
|
|
176
|
+
object = green
|
|
177
|
+
metrics = gray
|
|
178
|
+
text = white
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
The bottom status bar starts with `[ ]` when there is no observed uncommitted work and `[*]` when manual mode has pending changes. Commit and rollback messages include the local timestamp and the tracked row count, for example `Committed transaction, 2026-06-12 10:12:15, 7 row(s) changed`. Direct DML and ROWID grid edits contribute exact row counts; PL/SQL blocks can mark the transaction as pending with an unknown row count. Quitting or switching from manual mode to autocommit while changes are pending asks whether to commit, roll back, or cancel. The selected transaction mode is stored under `[database] autocommit` in the active `config.ini`.
|
|
182
|
+
|
|
183
|
+
Read-only mode is a client-side guardrail that rejects statements which the SQL scanner recognizes as database-writing. Select it with `--read-only`, `--read-write`, or `[database] read_only` in `config.ini`. It is not a security boundary: a function invoked by an otherwise valid `SELECT` can perform work outside the visible statement, including an autonomous transaction. Use an Oracle account with only the required privileges when writes must be prevented by the database. In read-only mode, `Ctrl-E` explains `SELECT` and `WITH` statements by opening a cursor and reading `DBMS_XPLAN.DISPLAY_CURSOR`; direct `EXPLAIN PLAN` remains disabled because it writes to `PLAN_TABLE`.
|
|
184
|
+
|
|
185
|
+
### Results And Explain Plan
|
|
186
|
+
|
|
187
|
+
| Key | Action |
|
|
188
|
+
| --- | --- |
|
|
189
|
+
| `Esc` / `Tab` | Return to the editor |
|
|
190
|
+
| Arrow keys | Move through result-grid cells |
|
|
191
|
+
| `PageUp` / `PageDown` | Move by a visible page in the result grid |
|
|
192
|
+
| `Home` / `End` | Move to the first/last result-grid column |
|
|
193
|
+
| `Ctrl-Home` / `Ctrl-End` | Move to the first/last result-grid row |
|
|
194
|
+
| `F8` | Toggle result grid / row-detail output |
|
|
195
|
+
| `F10` | View the full selected result cell |
|
|
196
|
+
| `Enter` | Edit the selected ROWID-backed result cell when available |
|
|
197
|
+
| `INS` | Prepare a draft insert row for ROWID-backed results |
|
|
198
|
+
| `Ctrl-Alt-C` | Insert the active draft row, or commit the transaction when no draft is active |
|
|
199
|
+
| `Up` / `Down` | Scroll explain-plan lines |
|
|
200
|
+
| `PageUp` / `PageDown` | Scroll explain-plan lines by page |
|
|
201
|
+
| `Home` / `End` | Move to the first/last explain-plan line |
|
|
202
|
+
|
|
203
|
+
When more result rows are available, `PageDown` at the loaded end fetches and appends the next result page. For simple single-table queries that select `ROWID`, press `Enter` on a non-`ROWID` cell to update that table column by rowid. Press `INS` in the grid to prepare a draft row at the top of the grid, edit its cells with `Enter`, use `Ctrl-Alt-C` to insert it, or use `Esc` to cancel it.
|
|
204
|
+
Database null values are displayed and entered as `<NULL>` in editable results. Plain `NULL` is stored as literal text.
|
|
205
|
+
`F7` cycles a grid fullscreen view that starts with the table header on the first terminal line and uses the last line for data, an editor-only fullscreen view, and a split layout with 2/3 editor and 1/3 data grid.
|
|
206
|
+
|
|
207
|
+
### Schema Browser
|
|
208
|
+
|
|
209
|
+
The `F9` schema browser groups tables, views, procedures, functions, packages, triggers, sequences, indexes, and private synonyms from the current schema. Type while the browser is focused to filter object names with a case-insensitive substring match; groups without matches are hidden and matching groups expand automatically without changing their saved expansion state.
|
|
210
|
+
|
|
211
|
+
| Key | Action |
|
|
212
|
+
| --- | --- |
|
|
213
|
+
| Printable text | Filter object names |
|
|
214
|
+
| `Backspace` | Delete the final filter character |
|
|
215
|
+
| `Esc` | Clear a nonempty filter, or return to the editor when the filter is empty |
|
|
216
|
+
| `Up` / `Down` | Move through browser entries |
|
|
217
|
+
| `PageUp` / `PageDown` | Move through browser entries by page |
|
|
218
|
+
| `Enter` | Expand a group or load an object definition |
|
|
219
|
+
| `Space` | Expand/collapse a group when the filter is empty, or add a space to the active filter |
|
|
220
|
+
| `Ctrl-R` | Refresh database objects |
|
|
221
|
+
|
|
222
|
+
### Cell Viewer
|
|
223
|
+
|
|
224
|
+
| Key | Action |
|
|
225
|
+
| --- | --- |
|
|
226
|
+
| `Esc` / `Enter` / `F10` | Close the cell viewer |
|
|
227
|
+
| `Up` / `Down` | Scroll cell text |
|
|
228
|
+
| `PageUp` / `PageDown` | Scroll cell text by page |
|
|
229
|
+
| `Home` / `End` | Move to the first/last cell-viewer line |
|
|
230
|
+
|
|
231
|
+
### Prompts And Pickers
|
|
232
|
+
|
|
233
|
+
| Key | Action |
|
|
234
|
+
| --- | --- |
|
|
235
|
+
| Printable text | Type into prompts or filter picker options |
|
|
236
|
+
| `Backspace` | Delete before the prompt cursor or picker filter |
|
|
237
|
+
| `Enter` | Accept the prompt or selected picker item |
|
|
238
|
+
| `Esc` / `Ctrl-Q` | Cancel the prompt or picker |
|
|
239
|
+
| `Up` / `Down` | Move through picker options |
|
|
240
|
+
| `PageUp` / `PageDown` | Move through picker options by page |
|
|
241
|
+
|
|
242
|
+
## Workspace Layout
|
|
243
|
+
|
|
244
|
+
```text
|
|
245
|
+
workspace/
|
|
246
|
+
sql/ saved SQL files
|
|
247
|
+
plsql/ saved PL/SQL files
|
|
248
|
+
results/ exported query output
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
The first launch creates the workspace folders and starter SQL/PLSQL files.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import configparser
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
import os
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
import re
|
|
8
|
+
import stat
|
|
9
|
+
import tempfile
|
|
10
|
+
from typing import Sequence
|
|
11
|
+
|
|
12
|
+
from platformdirs import user_config_path, user_data_path
|
|
13
|
+
|
|
14
|
+
from .loader import DEFAULT_DSN, load_config
|
|
15
|
+
from .models import AppConfig, SessionTab
|
|
16
|
+
from .paths import (
|
|
17
|
+
APP_NAME,
|
|
18
|
+
LEGACY_PASSWORD_FILE,
|
|
19
|
+
LEGACY_WORKSPACE_MARKERS,
|
|
20
|
+
SOURCE_CHECKOUT_MARKER,
|
|
21
|
+
is_legacy_source_workspace,
|
|
22
|
+
is_legacy_workspace,
|
|
23
|
+
nonblank_environment_value,
|
|
24
|
+
password_file_warnings,
|
|
25
|
+
platform_config_dir,
|
|
26
|
+
platform_workspace_dir,
|
|
27
|
+
read_password,
|
|
28
|
+
resolve_password_file,
|
|
29
|
+
resolve_workspace,
|
|
30
|
+
source_workspace_dir,
|
|
31
|
+
)
|
|
32
|
+
from .session import (
|
|
33
|
+
SESSION_TAB_PATH_PATTERN,
|
|
34
|
+
SESSION_TABS_SECTION,
|
|
35
|
+
read_session_coordinate,
|
|
36
|
+
read_session_tabs,
|
|
37
|
+
save_session_tabs,
|
|
38
|
+
session_path_text,
|
|
39
|
+
)
|
|
40
|
+
from .settings import (
|
|
41
|
+
EDITOR_COLOR_KINDS,
|
|
42
|
+
EDITOR_COLOR_NAME_VALUES,
|
|
43
|
+
EDITOR_COLOR_SECTION,
|
|
44
|
+
EXPLAIN_COLOR_KINDS,
|
|
45
|
+
EXPLAIN_COLOR_SECTION,
|
|
46
|
+
ensure_config_file,
|
|
47
|
+
ensure_database_option,
|
|
48
|
+
parse_editor_color,
|
|
49
|
+
read_autocommit,
|
|
50
|
+
read_color_section,
|
|
51
|
+
read_editor_colors,
|
|
52
|
+
read_explain_colors,
|
|
53
|
+
read_ini,
|
|
54
|
+
read_read_only,
|
|
55
|
+
read_remember_bind_values,
|
|
56
|
+
save_autocommit,
|
|
57
|
+
save_read_only,
|
|
58
|
+
write_ini_atomic,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
__all__ = (
|
|
63
|
+
"APP_NAME",
|
|
64
|
+
"AppConfig",
|
|
65
|
+
"DEFAULT_DSN",
|
|
66
|
+
"EDITOR_COLOR_KINDS",
|
|
67
|
+
"EDITOR_COLOR_NAME_VALUES",
|
|
68
|
+
"EDITOR_COLOR_SECTION",
|
|
69
|
+
"EXPLAIN_COLOR_KINDS",
|
|
70
|
+
"EXPLAIN_COLOR_SECTION",
|
|
71
|
+
"LEGACY_PASSWORD_FILE",
|
|
72
|
+
"LEGACY_WORKSPACE_MARKERS",
|
|
73
|
+
"Path",
|
|
74
|
+
"SESSION_TABS_SECTION",
|
|
75
|
+
"SESSION_TAB_PATH_PATTERN",
|
|
76
|
+
"SOURCE_CHECKOUT_MARKER",
|
|
77
|
+
"Sequence",
|
|
78
|
+
"SessionTab",
|
|
79
|
+
"annotations",
|
|
80
|
+
"configparser",
|
|
81
|
+
"dataclass",
|
|
82
|
+
"ensure_config_file",
|
|
83
|
+
"ensure_database_option",
|
|
84
|
+
"field",
|
|
85
|
+
"is_legacy_source_workspace",
|
|
86
|
+
"is_legacy_workspace",
|
|
87
|
+
"load_config",
|
|
88
|
+
"nonblank_environment_value",
|
|
89
|
+
"os",
|
|
90
|
+
"parse_editor_color",
|
|
91
|
+
"password_file_warnings",
|
|
92
|
+
"platform_config_dir",
|
|
93
|
+
"platform_workspace_dir",
|
|
94
|
+
"re",
|
|
95
|
+
"read_autocommit",
|
|
96
|
+
"read_color_section",
|
|
97
|
+
"read_editor_colors",
|
|
98
|
+
"read_explain_colors",
|
|
99
|
+
"read_ini",
|
|
100
|
+
"read_password",
|
|
101
|
+
"read_read_only",
|
|
102
|
+
"read_remember_bind_values",
|
|
103
|
+
"read_session_coordinate",
|
|
104
|
+
"read_session_tabs",
|
|
105
|
+
"resolve_password_file",
|
|
106
|
+
"resolve_workspace",
|
|
107
|
+
"save_autocommit",
|
|
108
|
+
"save_read_only",
|
|
109
|
+
"save_session_tabs",
|
|
110
|
+
"session_path_text",
|
|
111
|
+
"source_workspace_dir",
|
|
112
|
+
"stat",
|
|
113
|
+
"tempfile",
|
|
114
|
+
"user_config_path",
|
|
115
|
+
"user_data_path",
|
|
116
|
+
"write_ini_atomic",
|
|
117
|
+
)
|