plsqlwks 0.1.6__tar.gz → 0.1.7__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.7/MANIFEST.in +91 -0
- {plsqlwks-0.1.6/plsqlwks.egg-info → plsqlwks-0.1.7}/PKG-INFO +75 -9
- plsqlwks-0.1.7/QUICKSTART.md +288 -0
- plsqlwks-0.1.6/PKG-INFO → plsqlwks-0.1.7/README.md +72 -33
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/__init__.py +1 -1
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/config/models.py +1 -1
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/config/settings.py +10 -13
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/db/editing.py +51 -24
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/db/execution.py +404 -58
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/db/models.py +26 -1
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/db/session.py +17 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/exporting.py +75 -13
- plsqlwks-0.1.7/plsqlwks/sqlbinds.py +373 -0
- plsqlwks-0.1.7/plsqlwks/sqlsplit.py +836 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/ui/__init__.py +1 -1
- plsqlwks-0.1.7/plsqlwks/ui/app.py +356 -0
- plsqlwks-0.1.7/plsqlwks/ui/application_controller.py +88 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/ui/browser.py +4 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/ui/buffer.py +166 -28
- plsqlwks-0.1.6/plsqlwks/ui/app_tabs_browser.py → plsqlwks-0.1.7/plsqlwks/ui/catalog.py +173 -137
- plsqlwks-0.1.7/plsqlwks/ui/command_dispatcher.py +37 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/ui/commands.py +28 -1
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/ui/constants.py +1 -0
- plsqlwks-0.1.7/plsqlwks/ui/db_operations.py +396 -0
- plsqlwks-0.1.7/plsqlwks/ui/db_session.py +406 -0
- plsqlwks-0.1.7/plsqlwks/ui/db_worker.py +397 -0
- plsqlwks-0.1.7/plsqlwks/ui/dialogs.py +445 -0
- plsqlwks-0.1.7/plsqlwks/ui/documents.py +497 -0
- plsqlwks-0.1.6/plsqlwks/ui/app_editor.py → plsqlwks-0.1.7/plsqlwks/ui/editor_controller.py +359 -273
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/ui/errors.py +178 -7
- plsqlwks-0.1.7/plsqlwks/ui/input_controller.py +269 -0
- plsqlwks-0.1.7/plsqlwks/ui/key_reader.py +51 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/ui/keys.py +6 -3
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/ui/menu.py +11 -4
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/ui/plugin_host.py +3 -3
- plsqlwks-0.1.7/plsqlwks/ui/ports.py +71 -0
- plsqlwks-0.1.7/plsqlwks/ui/query_controller.py +596 -0
- plsqlwks-0.1.6/plsqlwks/ui/app_render.py → plsqlwks-0.1.7/plsqlwks/ui/renderer.py +122 -43
- plsqlwks-0.1.6/plsqlwks/ui/app_results.py → plsqlwks-0.1.7/plsqlwks/ui/result_controller.py +202 -98
- plsqlwks-0.1.7/plsqlwks/ui/result_presenter.py +766 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/ui/results.py +39 -4
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/ui/state.py +21 -0
- plsqlwks-0.1.7/plsqlwks/ui/viewport.py +256 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks.egg-info/SOURCES.txt +17 -31
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/pyproject.toml +13 -6
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/pytest.ini +1 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/tests/conftest.py +73 -6
- plsqlwks-0.1.6/MANIFEST.in +0 -8
- plsqlwks-0.1.6/README.md +0 -552
- plsqlwks-0.1.6/plsqlwks/sqlbinds.py +0 -163
- plsqlwks-0.1.6/plsqlwks/sqlsplit.py +0 -275
- plsqlwks-0.1.6/plsqlwks/ui/app.py +0 -194
- plsqlwks-0.1.6/plsqlwks/ui/app_db.py +0 -932
- plsqlwks-0.1.6/plsqlwks/ui/app_files.py +0 -468
- plsqlwks-0.1.6/plsqlwks/ui/app_input.py +0 -638
- plsqlwks-0.1.6/plsqlwks/ui/db_worker.py +0 -228
- plsqlwks-0.1.6/plsqlwks.egg-info/dependency_links.txt +0 -1
- plsqlwks-0.1.6/plsqlwks.egg-info/entry_points.txt +0 -2
- plsqlwks-0.1.6/plsqlwks.egg-info/requires.txt +0 -11
- plsqlwks-0.1.6/plsqlwks.egg-info/top_level.txt +0 -1
- plsqlwks-0.1.6/tests/test_config_workspace.py +0 -1014
- plsqlwks-0.1.6/tests/test_csv_export_plugin.py +0 -396
- plsqlwks-0.1.6/tests/test_db_editing.py +0 -947
- plsqlwks-0.1.6/tests/test_db_helpers.py +0 -1890
- plsqlwks-0.1.6/tests/test_db_worker.py +0 -464
- plsqlwks-0.1.6/tests/test_exporting.py +0 -276
- plsqlwks-0.1.6/tests/test_html_export_plugin.py +0 -739
- plsqlwks-0.1.6/tests/test_oracle_integration.py +0 -631
- plsqlwks-0.1.6/tests/test_packaging.py +0 -407
- plsqlwks-0.1.6/tests/test_plugins.py +0 -311
- plsqlwks-0.1.6/tests/test_pty_keys.py +0 -101
- plsqlwks-0.1.6/tests/test_rchar.py +0 -14
- plsqlwks-0.1.6/tests/test_sqlbinds.py +0 -133
- plsqlwks-0.1.6/tests/test_sqlsplit.py +0 -343
- plsqlwks-0.1.6/tests/test_ui_flows.py +0 -2887
- plsqlwks-0.1.6/tests/test_ui_keys.py +0 -4976
- plsqlwks-0.1.6/tests/test_ui_plugins.py +0 -907
- plsqlwks-0.1.6/tests/test_xlsx_export_plugin.py +0 -1139
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/PLUGINS.md +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/license.txt +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/__main__.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/config/__init__.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/config/loader.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/config/paths.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/config/session.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/db/__init__.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/db/explain.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/db/health.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/db/metadata.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/db/sql_analysis.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/db/transactions.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/html_exporting.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/plugins/__init__.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/plugins/_result_export.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/plugins/api.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/plugins/csv_export.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/plugins/html_export.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/plugins/loader.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/plugins/xlsx_export.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/ui/clipboard.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/ui/completion.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/ui/display.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/ui/help.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/ui/sql.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/ui/syntax.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/workspace.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plsqlwks/xlsx_exporting.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plugin-requirements/csv-export/requirements.txt +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plugin-requirements/html-export/requirements.txt +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/plugin-requirements/xlsx-export/requirements.txt +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/rchar.py +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/requirements.txt +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/setup.cfg +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/tests/fixtures/config_exports.txt +0 -0
- {plsqlwks-0.1.6 → plsqlwks-0.1.7}/tests/fixtures/ui_exports.txt +0 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Source distributions are intentionally allowlisted. Keep this list in sync
|
|
2
|
+
# with the exact artifact manifests asserted by tests/test_packaging.py.
|
|
3
|
+
global-exclude *
|
|
4
|
+
|
|
5
|
+
include MANIFEST.in
|
|
6
|
+
include PLUGINS.md
|
|
7
|
+
include QUICKSTART.md
|
|
8
|
+
include README.md
|
|
9
|
+
include license.txt
|
|
10
|
+
include pyproject.toml
|
|
11
|
+
include pytest.ini
|
|
12
|
+
include rchar.py
|
|
13
|
+
include requirements.txt
|
|
14
|
+
|
|
15
|
+
include plsqlwks/__init__.py
|
|
16
|
+
include plsqlwks/__main__.py
|
|
17
|
+
include plsqlwks/exporting.py
|
|
18
|
+
include plsqlwks/html_exporting.py
|
|
19
|
+
include plsqlwks/sqlbinds.py
|
|
20
|
+
include plsqlwks/sqlsplit.py
|
|
21
|
+
include plsqlwks/workspace.py
|
|
22
|
+
include plsqlwks/xlsx_exporting.py
|
|
23
|
+
|
|
24
|
+
include plsqlwks/config/__init__.py
|
|
25
|
+
include plsqlwks/config/loader.py
|
|
26
|
+
include plsqlwks/config/models.py
|
|
27
|
+
include plsqlwks/config/paths.py
|
|
28
|
+
include plsqlwks/config/session.py
|
|
29
|
+
include plsqlwks/config/settings.py
|
|
30
|
+
|
|
31
|
+
include plsqlwks/db/__init__.py
|
|
32
|
+
include plsqlwks/db/editing.py
|
|
33
|
+
include plsqlwks/db/execution.py
|
|
34
|
+
include plsqlwks/db/explain.py
|
|
35
|
+
include plsqlwks/db/health.py
|
|
36
|
+
include plsqlwks/db/metadata.py
|
|
37
|
+
include plsqlwks/db/models.py
|
|
38
|
+
include plsqlwks/db/session.py
|
|
39
|
+
include plsqlwks/db/sql_analysis.py
|
|
40
|
+
include plsqlwks/db/transactions.py
|
|
41
|
+
|
|
42
|
+
include plsqlwks/plugins/__init__.py
|
|
43
|
+
include plsqlwks/plugins/_result_export.py
|
|
44
|
+
include plsqlwks/plugins/api.py
|
|
45
|
+
include plsqlwks/plugins/csv_export.py
|
|
46
|
+
include plsqlwks/plugins/html_export.py
|
|
47
|
+
include plsqlwks/plugins/loader.py
|
|
48
|
+
include plsqlwks/plugins/xlsx_export.py
|
|
49
|
+
|
|
50
|
+
include plsqlwks/ui/__init__.py
|
|
51
|
+
include plsqlwks/ui/app.py
|
|
52
|
+
include plsqlwks/ui/application_controller.py
|
|
53
|
+
include plsqlwks/ui/browser.py
|
|
54
|
+
include plsqlwks/ui/buffer.py
|
|
55
|
+
include plsqlwks/ui/catalog.py
|
|
56
|
+
include plsqlwks/ui/clipboard.py
|
|
57
|
+
include plsqlwks/ui/command_dispatcher.py
|
|
58
|
+
include plsqlwks/ui/commands.py
|
|
59
|
+
include plsqlwks/ui/completion.py
|
|
60
|
+
include plsqlwks/ui/constants.py
|
|
61
|
+
include plsqlwks/ui/db_operations.py
|
|
62
|
+
include plsqlwks/ui/db_session.py
|
|
63
|
+
include plsqlwks/ui/db_worker.py
|
|
64
|
+
include plsqlwks/ui/dialogs.py
|
|
65
|
+
include plsqlwks/ui/display.py
|
|
66
|
+
include plsqlwks/ui/documents.py
|
|
67
|
+
include plsqlwks/ui/editor_controller.py
|
|
68
|
+
include plsqlwks/ui/errors.py
|
|
69
|
+
include plsqlwks/ui/help.py
|
|
70
|
+
include plsqlwks/ui/input_controller.py
|
|
71
|
+
include plsqlwks/ui/key_reader.py
|
|
72
|
+
include plsqlwks/ui/keys.py
|
|
73
|
+
include plsqlwks/ui/menu.py
|
|
74
|
+
include plsqlwks/ui/plugin_host.py
|
|
75
|
+
include plsqlwks/ui/ports.py
|
|
76
|
+
include plsqlwks/ui/query_controller.py
|
|
77
|
+
include plsqlwks/ui/renderer.py
|
|
78
|
+
include plsqlwks/ui/result_controller.py
|
|
79
|
+
include plsqlwks/ui/result_presenter.py
|
|
80
|
+
include plsqlwks/ui/results.py
|
|
81
|
+
include plsqlwks/ui/sql.py
|
|
82
|
+
include plsqlwks/ui/state.py
|
|
83
|
+
include plsqlwks/ui/syntax.py
|
|
84
|
+
include plsqlwks/ui/viewport.py
|
|
85
|
+
|
|
86
|
+
include plugin-requirements/csv-export/requirements.txt
|
|
87
|
+
include plugin-requirements/html-export/requirements.txt
|
|
88
|
+
include plugin-requirements/xlsx-export/requirements.txt
|
|
89
|
+
include tests/conftest.py
|
|
90
|
+
include tests/fixtures/config_exports.txt
|
|
91
|
+
include tests/fixtures/ui_exports.txt
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plsqlwks
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.7
|
|
4
4
|
Summary: An ncurses SQL and PL/SQL workspace for Oracle databases.
|
|
5
|
+
Author: unu2000
|
|
5
6
|
License-Expression: LicenseRef-plsqlwks-Donationware
|
|
6
7
|
Project-URL: Repository, https://gitlab.com/unununu/plsqlwks
|
|
7
8
|
Project-URL: Issues, https://gitlab.com/unununu/plsqlwks/-/issues
|
|
8
9
|
Project-URL: Changelog, https://gitlab.com/unununu/plsqlwks/-/blob/main/CHANGELOG.md
|
|
10
|
+
Project-URL: Ko-fi, https://ko-fi.com/unu2000
|
|
9
11
|
Classifier: Programming Language :: Python :: 3
|
|
10
12
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
11
13
|
Classifier: Topic :: Database
|
|
@@ -27,8 +29,19 @@ Dynamic: license-file
|
|
|
27
29
|
|
|
28
30
|
An ncurses SQL and PL/SQL workspace for Oracle databases.
|
|
29
31
|
|
|
32
|
+
Author and support: [unu2000 on Ko-fi](https://ko-fi.com/unu2000).
|
|
33
|
+
|
|
34
|
+
The supported and continuously tested database releases are Oracle Database
|
|
35
|
+
19c and Oracle AI Database 26ai. See the
|
|
36
|
+
[Oracle compatibility matrix](https://gitlab.com/unununu/plsqlwks/-/blob/main/COMPATIBILITY.md) for the tested connection and
|
|
37
|
+
privilege profiles, safety gate, and integration-test setup.
|
|
38
|
+
|
|
30
39
|

|
|
31
40
|
|
|
41
|
+
New here? Follow the [installation-to-first-query quick start](QUICKSTART.md)
|
|
42
|
+
for copy-ready connection setup, screenshots, practical SQL workflows,
|
|
43
|
+
troubleshooting, and a complete installed-plugin example.
|
|
44
|
+
|
|
32
45
|
## Connection
|
|
33
46
|
|
|
34
47
|
The default connection is:
|
|
@@ -85,7 +98,7 @@ python3 -m pip install .
|
|
|
85
98
|
Run the default test and lint checks from a development checkout with:
|
|
86
99
|
|
|
87
100
|
```bash
|
|
88
|
-
python3 -m pytest -q
|
|
101
|
+
python3 -m pytest -q --maxfail=1
|
|
89
102
|
python3 -m ruff check .
|
|
90
103
|
```
|
|
91
104
|
|
|
@@ -93,8 +106,8 @@ Plugin API and built-in plugin tests are optional and are not part of the
|
|
|
93
106
|
default core test run. Run them with either opt-in form:
|
|
94
107
|
|
|
95
108
|
```bash
|
|
96
|
-
PLSQLWKS_TEST_PLUGINS=1 python3 -m pytest -q
|
|
97
|
-
python3 -m pytest -q -m plugin
|
|
109
|
+
PLSQLWKS_TEST_PLUGINS=1 python3 -m pytest -q --maxfail=1
|
|
110
|
+
python3 -m pytest -q --maxfail=1 -m plugin
|
|
98
111
|
```
|
|
99
112
|
|
|
100
113
|
The CSV and HTML export plugins have no additional dependencies. XLSX export
|
|
@@ -111,11 +124,26 @@ retains `plugin-requirements/xlsx-export/requirements.txt` as a compatible
|
|
|
111
124
|
fallback for existing checkout automation.
|
|
112
125
|
|
|
113
126
|
Oracle integration tests require the connection environment variables shown
|
|
114
|
-
above and
|
|
127
|
+
above and a nonempty regular password file. Setting `PLSQLWKS_TEST_ORACLE=1`
|
|
128
|
+
is an explicit opt-in, so invalid or missing credentials fail collection rather
|
|
129
|
+
than silently skipping the live suite. Set `PLSQLWKS_TEST_ORACLE_TARGET` to
|
|
130
|
+
`19c` or `26ai` when the test run must verify that it reached the intended
|
|
131
|
+
server release:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
PLSQLWKS_TEST_ORACLE=1 PLSQLWKS_TEST_ORACLE_TARGET=19c \
|
|
135
|
+
python3 -m pytest -q -m oracle --maxfail=1
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Omit the target for an ad-hoc run against another reachable Oracle database.
|
|
139
|
+
The complete release-gating setup, including the developer, DML-only, and
|
|
140
|
+
read-only profiles, is documented in the
|
|
141
|
+
[Oracle compatibility matrix](https://gitlab.com/unununu/plsqlwks/-/blob/main/COMPATIBILITY.md).
|
|
142
|
+
Enable every optional test group with:
|
|
115
143
|
|
|
116
144
|
```bash
|
|
117
145
|
PLSQLWKS_TEST_ORACLE=1 PLSQLWKS_TEST_PLUGINS=1 PLSQLWKS_TEST_PTY=1 PLSQLWKS_TEST_SLOW=1 \
|
|
118
|
-
python3 -m pytest -q -rs
|
|
146
|
+
python3 -m pytest -q -rs --maxfail=1
|
|
119
147
|
```
|
|
120
148
|
|
|
121
149
|
## Run
|
|
@@ -136,6 +164,11 @@ The CLI option takes precedence over `PLSQLWKS_WORKSPACE`. For compatibility, a
|
|
|
136
164
|
source checkout that already contains a configured `workspace/` continues to
|
|
137
165
|
use it and displays a migration notice; files are never moved automatically.
|
|
138
166
|
|
|
167
|
+
Fresh workspaces start in manual transaction mode and write
|
|
168
|
+
`[database] autocommit = no` to their generated `config.ini`. Existing explicit
|
|
169
|
+
`yes` or `no` settings are preserved; a missing or malformed setting uses the
|
|
170
|
+
safe manual fallback.
|
|
171
|
+
|
|
139
172
|
Choose the initial transaction mode for one invocation with `--manual` or
|
|
140
173
|
`--autocommit`. These options override `[database] autocommit` from the active
|
|
141
174
|
`config.ini`:
|
|
@@ -176,9 +209,21 @@ explicitly, so Oracle rolls its uncommitted work back.
|
|
|
176
209
|
If the old connection is already dead and reports an error while closing,
|
|
177
210
|
plsqlwks still attempts the replacement connection and reports the close error
|
|
178
211
|
as a warning after a successful reconnect.
|
|
212
|
+
An unexpected connection loss is shown in the header and status bar. Rows that
|
|
213
|
+
were already loaded remain available for viewing, but paging, editing, and
|
|
214
|
+
inserting are disabled until reconnect because their live cursor/session state
|
|
215
|
+
is no longer valid. If manual work may have been pending, the status explicitly
|
|
216
|
+
warns that the transaction outcome is unknown.
|
|
179
217
|
|
|
180
218
|
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.
|
|
181
219
|
|
|
220
|
+
Worksheet and configuration saves replace their destination atomically while
|
|
221
|
+
preserving an existing file's POSIX permission bits. A
|
|
222
|
+
file-backed worksheet also detects when its file was changed or deleted outside
|
|
223
|
+
plsqlwks and asks whether to overwrite it, save under another name, or cancel.
|
|
224
|
+
Undo and redo update the unsaved-change marker by comparing the current content
|
|
225
|
+
with the last successful save.
|
|
226
|
+
|
|
182
227
|
## Keys
|
|
183
228
|
|
|
184
229
|
### Global
|
|
@@ -227,7 +272,7 @@ After a successful quit, plsqlwks records the open file-backed tabs, active tab,
|
|
|
227
272
|
| `F4` | New template |
|
|
228
273
|
| `F5` / `Ctrl-Enter` / `Alt-X` | Execute selected SQL or current statement |
|
|
229
274
|
| `F11` | Execute selected SQL or whole buffer as a script |
|
|
230
|
-
| `Alt-G` | Generate SELECT, INSERT, or UPDATE with table columns |
|
|
275
|
+
| `Alt-G` | Generate SELECT, INSERT, or UPDATE with table or view columns |
|
|
231
276
|
| `Alt-+` | Refresh autocomplete metadata cache |
|
|
232
277
|
| `Alt-R` | Rename current buffer |
|
|
233
278
|
| `Ctrl-T` | New file tab |
|
|
@@ -246,7 +291,18 @@ After a successful quit, plsqlwks records the open file-backed tabs, active tab,
|
|
|
246
291
|
| `Ctrl+=` | Reconnect |
|
|
247
292
|
|
|
248
293
|
Use `/` on a line by itself after PL/SQL objects or anonymous blocks when running a script.
|
|
249
|
-
|
|
294
|
+
Script execution reports statement progress as `n/total` and stops at the first
|
|
295
|
+
failed statement while preserving earlier results. Scripts are sent directly to
|
|
296
|
+
Oracle, not through SQL*Plus or SQLcl: client commands such as `PROMPT`, `SPOOL`,
|
|
297
|
+
and `SET SERVEROUTPUT`, and `&`/`&&` substitution variables, are rejected before
|
|
298
|
+
bind prompts or execution. Oracle SQL statements such as `SET TRANSACTION`
|
|
299
|
+
remain supported.
|
|
300
|
+
Execution and explain errors report mapped editor line and column diagnostics.
|
|
301
|
+
The cursor moves only when the buffer still matches the source that was sent to
|
|
302
|
+
Oracle; if it changed while the operation ran, the result warns about the stale
|
|
303
|
+
source instead. Use `Alt-O -> Editor -> Next execution diagnostic` or
|
|
304
|
+
`Previous execution diagnostic` to visit additional locations from the most
|
|
305
|
+
recent unchanged source.
|
|
250
306
|
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.
|
|
251
307
|
Unquoted bind names are case-insensitive, so `:id` and `:ID` share one prompt and value. Quoted bind names remain case-sensitive.
|
|
252
308
|
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.
|
|
@@ -293,6 +349,7 @@ Read-only mode is a client-side guardrail that rejects statements which the SQL
|
|
|
293
349
|
| `Home` / `End` | Move to the first/last result-grid column |
|
|
294
350
|
| `Ctrl-Home` / `Ctrl-End` | Move to the first/last result-grid row |
|
|
295
351
|
| `F8` | Toggle result grid / row-detail output |
|
|
352
|
+
| `Ctrl-C` | Copy the selected result cell to the clipboard |
|
|
296
353
|
| `F10` | View the full selected result cell |
|
|
297
354
|
| `Enter` | Edit the selected ROWID-backed result cell when available |
|
|
298
355
|
| `INS` | Prepare a draft insert row for ROWID-backed results |
|
|
@@ -307,7 +364,11 @@ unquoted current-schema table that include `ROWID`, press `Enter` on a directly
|
|
|
307
364
|
selected unquoted table column to update it by rowid. Press `INS` in the grid to
|
|
308
365
|
prepare a draft row at the top of the grid, edit its cells with `Enter`, use
|
|
309
366
|
`Ctrl-Alt-C` to insert it, or use `Esc` to cancel it.
|
|
310
|
-
|
|
367
|
+
While entering a cell, use Left/Right or Home/End to move within the existing
|
|
368
|
+
text and Backspace/Delete to edit around the cursor. DATE and TIMESTAMP cells
|
|
369
|
+
offer a choice between an ISO value and database-side `SYSDATE`.
|
|
370
|
+
Database null values are displayed and entered as `<NULL>` in editable results.
|
|
371
|
+
Plain `NULL` is stored as literal text.
|
|
311
372
|
Grid edits compare the selected cell's originally loaded typed value as well as
|
|
312
373
|
the `ROWID`. If another session changes that cell or deletes the row first, the
|
|
313
374
|
edit is rejected and the query must be refreshed. Changes to other cells in the
|
|
@@ -320,6 +381,11 @@ precision above six, are read-only in the grid.
|
|
|
320
381
|
Displayed CLOB and BLOB values are limited to the first 65,536 characters or
|
|
321
382
|
bytes and include a truncation marker with the full size. Truncated LOB cells
|
|
322
383
|
cannot be edited safely. Schema-browser DDL is always read in full.
|
|
384
|
+
DBMS_OUTPUT is collected after each statement and after every fetched result
|
|
385
|
+
page without replacing a real query grid. Output-read or cursor-cleanup failures
|
|
386
|
+
are displayed as warnings while preserving successfully fetched rows. PL/SQL
|
|
387
|
+
compiler warnings are also retained with successful statement results; compiler
|
|
388
|
+
errors remain execution failures with navigable source locations.
|
|
323
389
|
`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.
|
|
324
390
|
|
|
325
391
|
To export the active table, use one of these command paths:
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
# PLSQLWKS quick start
|
|
2
|
+
|
|
3
|
+
This guide goes from a source checkout to a first Oracle query in about five
|
|
4
|
+
minutes. It then covers a few useful query workflows, the most common startup
|
|
5
|
+
problems, and a small installed plugin. For the complete key reference and
|
|
6
|
+
runtime behavior, see [README.md](README.md); for the full extension contract,
|
|
7
|
+
see [PLUGINS.md](PLUGINS.md).
|
|
8
|
+
|
|
9
|
+
## 1. Check the prerequisites
|
|
10
|
+
|
|
11
|
+
You need:
|
|
12
|
+
|
|
13
|
+
- Python 3.10 or newer with the standard-library `curses` module
|
|
14
|
+
- a terminal with at least 80 columns and 24 rows
|
|
15
|
+
- an Oracle username, password, and Easy Connect service name
|
|
16
|
+
- network access to the Oracle listener
|
|
17
|
+
|
|
18
|
+
The DSN in this guide has the form `host:port/service_name`, for example
|
|
19
|
+
`db.example.test:1521/freepdb1`. Ask the database administrator for the exact
|
|
20
|
+
value when in doubt; a service name is not necessarily the same as an Oracle
|
|
21
|
+
SID.
|
|
22
|
+
|
|
23
|
+
## 2. Install PLSQLWKS
|
|
24
|
+
|
|
25
|
+
From a checkout of the repository, create an isolated environment and install
|
|
26
|
+
the application:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
python3 -m venv .venv
|
|
30
|
+
source .venv/bin/activate
|
|
31
|
+
python3 -m pip install --upgrade pip
|
|
32
|
+
python3 -m pip install .
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Confirm that the console command is available:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
plsqlwks --help
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
For development, replace the final install command with
|
|
42
|
+
`python3 -m pip install -e '.[dev]'`.
|
|
43
|
+
|
|
44
|
+
## 3. Configure the Oracle connection
|
|
45
|
+
|
|
46
|
+
The following Bash example prompts without echoing the password, creates a
|
|
47
|
+
private password file, and exports the connection for the current shell. Change
|
|
48
|
+
the user and DSN to match the target database.
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
config_dir="${XDG_CONFIG_HOME:-$HOME/.config}/plsqlwks"
|
|
52
|
+
mkdir -p "$config_dir"
|
|
53
|
+
chmod 700 "$config_dir"
|
|
54
|
+
umask 077
|
|
55
|
+
IFS= read -r -s -p "Oracle password: " oracle_password
|
|
56
|
+
printf '\n'
|
|
57
|
+
printf '%s' "$oracle_password" > "$config_dir/orapass"
|
|
58
|
+
unset oracle_password
|
|
59
|
+
|
|
60
|
+
export ORACLE_USER='hr'
|
|
61
|
+
export ORACLE_PASSWORD_FILE="$config_dir/orapass"
|
|
62
|
+
export ORACLE_DSN='127.0.0.1:1521/free'
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
PLSQLWKS preserves spaces in the password and removes only final CR/LF line
|
|
66
|
+
endings. Keep the password file private; on POSIX systems its mode should be
|
|
67
|
+
`0600`.
|
|
68
|
+
|
|
69
|
+
These variables override the built-in defaults. To keep them across terminal
|
|
70
|
+
sessions, add only the three `export` lines to the shell profile; do not put the
|
|
71
|
+
password itself in the profile.
|
|
72
|
+
|
|
73
|
+
## 4. Run the first query
|
|
74
|
+
|
|
75
|
+
Start in manual transaction mode:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
plsqlwks --manual
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The header should say `db connected`. Enter this query in the upper editor:
|
|
82
|
+
|
|
83
|
+
```sql
|
|
84
|
+
select
|
|
85
|
+
sys_context('USERENV', 'SESSION_USER') as session_user,
|
|
86
|
+
sys_context('USERENV', 'DB_NAME') as database_name,
|
|
87
|
+
to_char(systimestamp, 'YYYY-MM-DD HH24:MI:SS TZH:TZM') as database_time
|
|
88
|
+
from dual;
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Press `F5`, `Ctrl-Enter`, or `Alt-X`. The lower pane shows one row from the
|
|
92
|
+
connected database. Press `Tab` to focus the grid, arrow keys to move between
|
|
93
|
+
cells, and `Tab` again to return to the editor. Press `Ctrl-Q` to quit.
|
|
94
|
+
|
|
95
|
+

|
|
96
|
+
|
|
97
|
+
The result is a connection check that does not depend on application tables or
|
|
98
|
+
sample schemas. The displayed user and database name should match the intended
|
|
99
|
+
target before running any write statement.
|
|
100
|
+
|
|
101
|
+
## Practical query examples
|
|
102
|
+
|
|
103
|
+
### Prompt for a bind value
|
|
104
|
+
|
|
105
|
+
Execute this statement with `F5`:
|
|
106
|
+
|
|
107
|
+
```sql
|
|
108
|
+
select :name as supplied_name,
|
|
109
|
+
'Hello, ' || :name as greeting
|
|
110
|
+
from dual;
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
PLSQLWKS prompts once for `:name` and passes the answer as an Oracle bind value.
|
|
114
|
+
Set `[database] remember_bind_values = yes` in the active `config.ini` if the
|
|
115
|
+
same bind should be prefilled later in the application session.
|
|
116
|
+
|
|
117
|
+
### Run a script and inspect DBMS_OUTPUT
|
|
118
|
+
|
|
119
|
+
Use `F11` for a multi-statement script:
|
|
120
|
+
|
|
121
|
+
```sql
|
|
122
|
+
begin
|
|
123
|
+
dbms_output.put_line(
|
|
124
|
+
'Connected as ' || sys_context('USERENV', 'SESSION_USER')
|
|
125
|
+
);
|
|
126
|
+
end;
|
|
127
|
+
/
|
|
128
|
+
|
|
129
|
+
select count(*) as visible_objects
|
|
130
|
+
from user_objects;
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
`F11` runs the whole buffer (or the selection). Press `F6` to switch between
|
|
134
|
+
normal results and captured `DBMS_OUTPUT`.
|
|
135
|
+
|
|
136
|
+
### Page through a larger result
|
|
137
|
+
|
|
138
|
+
If the connected schema has the Oracle HR sample tables, try:
|
|
139
|
+
|
|
140
|
+
```sql
|
|
141
|
+
select employee_id, first_name, last_name, department_id
|
|
142
|
+
from employees
|
|
143
|
+
order by employee_id;
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`PLSQLWKS_MAX_ROWS` controls the number of rows loaded per page. With the result
|
|
147
|
+
grid focused, use `Ctrl-PageDown` and `Ctrl-PageUp` to page. The status and
|
|
148
|
+
result label say when more rows are available.
|
|
149
|
+
|
|
150
|
+
### Export loaded rows
|
|
151
|
+
|
|
152
|
+
With a table result visible, press `Alt-O`, type `export`, and choose CSV, HTML,
|
|
153
|
+
or XLSX. The export contains exactly the rows currently loaded in the grid and
|
|
154
|
+
defaults to the workspace `results/` directory. XLSX support requires
|
|
155
|
+
`python3 -m pip install 'plsqlwks[xlsx]'`.
|
|
156
|
+
|
|
157
|
+
### Commit or roll back deliberately
|
|
158
|
+
|
|
159
|
+
Fresh workspaces use manual transactions. After a DML statement, use
|
|
160
|
+
`Ctrl-Alt-C` to commit or `Ctrl-Alt-R` to roll back. `F12` changes transaction
|
|
161
|
+
mode. The `--read-only` option adds a client-side guardrail against statements
|
|
162
|
+
that appear to write, but database privileges remain the security boundary.
|
|
163
|
+
|
|
164
|
+
## Troubleshooting
|
|
165
|
+
|
|
166
|
+
| Symptom | What to check |
|
|
167
|
+
| --- | --- |
|
|
168
|
+
| `No module named _curses` or `curses` | Use a Python build and terminal that provide curses. On native Windows, a supported WSL environment is usually the simplest route. |
|
|
169
|
+
| `Password file is missing` | Check `ORACLE_PASSWORD_FILE`, create the file, and restart. The path must name a nonempty regular file. |
|
|
170
|
+
| Password permission warning | Run `chmod 600 "$ORACLE_PASSWORD_FILE"`; also keep its parent directory private. |
|
|
171
|
+
| `ORA-01017` | Recheck `ORACLE_USER`, rewrite the password file without adding unintended characters, and confirm that the account is valid for this service. |
|
|
172
|
+
| `ORA-12514` or `ORA-12154` | Recheck the service name in `ORACLE_DSN`. Easy Connect uses `host:port/service_name`. |
|
|
173
|
+
| `ORA-12541`, timeout, or connection refused | Check host, port, listener availability, VPN, firewall, and DNS from the same terminal. |
|
|
174
|
+
| Header says `db disconnected` after a network problem | Loaded rows remain viewable. Restore connectivity and press `Ctrl+=` to reconnect; if manual work was pending, treat its outcome as unknown until verified. |
|
|
175
|
+
| `Ctrl-Enter` inserts a newline or is not recognized | Terminal key encodings vary. Use `F5` or `Alt-X`, which run the same current-statement action. |
|
|
176
|
+
| Box drawing or non-ASCII text is garbled | Start from a UTF-8 locale such as `C.UTF-8`; check the available names with `locale -a`. |
|
|
177
|
+
| The UI is clipped or a picker will not open | Enlarge the terminal to at least 80 columns by 24 rows. |
|
|
178
|
+
| A write statement is rejected in read-only mode | Restart with `--read-write` only if the account and task are intended to allow writes. |
|
|
179
|
+
| XLSX export reports that `openpyxl` is missing | Install the optional extra with `python3 -m pip install 'plsqlwks[xlsx]'`, then restart. |
|
|
180
|
+
|
|
181
|
+
Press `F1` at any time for the in-application key guide. Connection errors and
|
|
182
|
+
plugin failures are reported in the lower pane; the final status line provides
|
|
183
|
+
the shorter summary.
|
|
184
|
+
|
|
185
|
+
## Develop a small command plugin
|
|
186
|
+
|
|
187
|
+
Plugin API v1 loads trusted Python packages in the PLSQLWKS process. This
|
|
188
|
+
example adds two commands: one reports the loaded-row count, and the other
|
|
189
|
+
prompts for a label. It needs no dependency beyond PLSQLWKS.
|
|
190
|
+
|
|
191
|
+
Create this layout outside the PLSQLWKS repository:
|
|
192
|
+
|
|
193
|
+
```text
|
|
194
|
+
result-tools/
|
|
195
|
+
pyproject.toml
|
|
196
|
+
src/
|
|
197
|
+
result_tools/
|
|
198
|
+
__init__.py
|
|
199
|
+
plugin.py
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Use this `pyproject.toml`:
|
|
203
|
+
|
|
204
|
+
```toml
|
|
205
|
+
[build-system]
|
|
206
|
+
requires = ["setuptools>=77"]
|
|
207
|
+
build-backend = "setuptools.build_meta"
|
|
208
|
+
|
|
209
|
+
[project]
|
|
210
|
+
name = "plsqlwks-result-tools"
|
|
211
|
+
version = "0.1.0"
|
|
212
|
+
requires-python = ">=3.10"
|
|
213
|
+
dependencies = ["plsqlwks>=0.1.7"]
|
|
214
|
+
|
|
215
|
+
[project.entry-points."plsqlwks.plugins"]
|
|
216
|
+
result-tools = "result_tools.plugin:create_plugin"
|
|
217
|
+
|
|
218
|
+
[tool.setuptools.packages.find]
|
|
219
|
+
where = ["src"]
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Leave `src/result_tools/__init__.py` empty and put this in
|
|
223
|
+
`src/result_tools/plugin.py`:
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
from plsqlwks.plugins import Plugin, PluginCommand, PluginContext
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def show_loaded_count(context: PluginContext) -> None:
|
|
230
|
+
result = context.get_active_result()
|
|
231
|
+
if result is None:
|
|
232
|
+
context.set_status("No table result is active")
|
|
233
|
+
return
|
|
234
|
+
suffix = "; more rows exist" if result.has_more else ""
|
|
235
|
+
context.set_status(f"{len(result.rows)} loaded row(s){suffix}")
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def label_loaded_result(context: PluginContext) -> None:
|
|
239
|
+
result = context.get_active_result()
|
|
240
|
+
if result is None:
|
|
241
|
+
context.set_status("No table result is active")
|
|
242
|
+
return
|
|
243
|
+
label = context.prompt_text("Result label", result.title)
|
|
244
|
+
if label is not None:
|
|
245
|
+
context.set_status(f"{label}: {len(result.rows)} loaded row(s)")
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def create_plugin() -> Plugin:
|
|
249
|
+
return Plugin(
|
|
250
|
+
id="result-tools",
|
|
251
|
+
name="Result tools",
|
|
252
|
+
commands=(
|
|
253
|
+
PluginCommand(
|
|
254
|
+
id="show-loaded-count",
|
|
255
|
+
section="Results",
|
|
256
|
+
title="Show loaded row count",
|
|
257
|
+
handler=show_loaded_count,
|
|
258
|
+
keywords="plugin snapshot rows",
|
|
259
|
+
),
|
|
260
|
+
PluginCommand(
|
|
261
|
+
id="label-loaded-result",
|
|
262
|
+
section="Results",
|
|
263
|
+
title="Label loaded result",
|
|
264
|
+
handler=label_loaded_result,
|
|
265
|
+
keywords="plugin prompt snapshot",
|
|
266
|
+
),
|
|
267
|
+
),
|
|
268
|
+
)
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Install it into the same virtual environment and perform a factory smoke test:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
python3 -m pip install -e /path/to/result-tools
|
|
275
|
+
python3 -c "from result_tools.plugin import create_plugin; print(create_plugin())"
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Restart PLSQLWKS, open `Alt-O`, and search for `loaded`. Plugin factories are
|
|
279
|
+
discovered only at startup. A bad plugin is skipped with a startup warning, and
|
|
280
|
+
an exception from a command is shown in the UI rather than ending the session.
|
|
281
|
+
|
|
282
|
+
Handlers receive an immutable snapshot of already loaded display rows and a
|
|
283
|
+
small UI-mediated context. API v1 intentionally does not expose database
|
|
284
|
+
execution, Oracle handles, mutable application state, curses drawing, global
|
|
285
|
+
shortcuts, background jobs, lifecycle hooks, or hot reload. Installed plugins
|
|
286
|
+
are not sandboxed, so install them only from sources you trust. Continue with
|
|
287
|
+
[PLUGINS.md](PLUGINS.md) for export-plugin examples, validation rules, optional
|
|
288
|
+
dependencies, and plugin test commands.
|