tsdb-sql-tool 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.
Files changed (108) hide show
  1. tsdb_sql_tool-0.1.0/.coverage +0 -0
  2. tsdb_sql_tool-0.1.0/.envrc +5 -0
  3. tsdb_sql_tool-0.1.0/CONTRIBUTING.md +134 -0
  4. tsdb_sql_tool-0.1.0/LICENSE +21 -0
  5. tsdb_sql_tool-0.1.0/PKG-INFO +309 -0
  6. tsdb_sql_tool-0.1.0/README.md +274 -0
  7. tsdb_sql_tool-0.1.0/config.example.toml +29 -0
  8. tsdb_sql_tool-0.1.0/coverage.xml +1656 -0
  9. tsdb_sql_tool-0.1.0/htmlcov/.gitignore +2 -0
  10. tsdb_sql_tool-0.1.0/htmlcov/class_index.html +581 -0
  11. tsdb_sql_tool-0.1.0/htmlcov/coverage_html_cb_dd2e7eb5.js +735 -0
  12. tsdb_sql_tool-0.1.0/htmlcov/favicon_32_cb_c827f16f.png +0 -0
  13. tsdb_sql_tool-0.1.0/htmlcov/function_index.html +1651 -0
  14. tsdb_sql_tool-0.1.0/htmlcov/index.html +360 -0
  15. tsdb_sql_tool-0.1.0/htmlcov/keybd_closed_cb_900cfef5.png +0 -0
  16. tsdb_sql_tool-0.1.0/htmlcov/status.json +1 -0
  17. tsdb_sql_tool-0.1.0/htmlcov/style_cb_9ff733b0.css +389 -0
  18. tsdb_sql_tool-0.1.0/htmlcov/z_37ef60047406d5f4___init___py.html +97 -0
  19. tsdb_sql_tool-0.1.0/htmlcov/z_37ef60047406d5f4__shared_py.html +222 -0
  20. tsdb_sql_tool-0.1.0/htmlcov/z_37ef60047406d5f4_config_py.html +215 -0
  21. tsdb_sql_tool-0.1.0/htmlcov/z_37ef60047406d5f4_query_py.html +132 -0
  22. tsdb_sql_tool-0.1.0/htmlcov/z_37ef60047406d5f4_service_py.html +191 -0
  23. tsdb_sql_tool-0.1.0/htmlcov/z_37ef60047406d5f4_ts_py.html +1116 -0
  24. tsdb_sql_tool-0.1.0/htmlcov/z_557e2ead8ffa2dd8___init___py.html +103 -0
  25. tsdb_sql_tool-0.1.0/htmlcov/z_557e2ead8ffa2dd8_base_py.html +151 -0
  26. tsdb_sql_tool-0.1.0/htmlcov/z_557e2ead8ffa2dd8_csv_py.html +133 -0
  27. tsdb_sql_tool-0.1.0/htmlcov/z_557e2ead8ffa2dd8_json_py.html +138 -0
  28. tsdb_sql_tool-0.1.0/htmlcov/z_557e2ead8ffa2dd8_table_py.html +150 -0
  29. tsdb_sql_tool-0.1.0/htmlcov/z_a4c62730d80e47ff___init___py.html +97 -0
  30. tsdb_sql_tool-0.1.0/htmlcov/z_a4c62730d80e47ff_helpers_py.html +218 -0
  31. tsdb_sql_tool-0.1.0/htmlcov/z_a4c62730d80e47ff_main_py.html +1021 -0
  32. tsdb_sql_tool-0.1.0/htmlcov/z_a4c62730d80e47ff_output_py.html +161 -0
  33. tsdb_sql_tool-0.1.0/htmlcov/z_c666155f4fe56d54___init___py.html +102 -0
  34. tsdb_sql_tool-0.1.0/htmlcov/z_c666155f4fe56d54___main___py.html +103 -0
  35. tsdb_sql_tool-0.1.0/htmlcov/z_df7d085f4a86470d___init___py.html +97 -0
  36. tsdb_sql_tool-0.1.0/htmlcov/z_df7d085f4a86470d_client_py.html +230 -0
  37. tsdb_sql_tool-0.1.0/htmlcov/z_df7d085f4a86470d_config_py.html +375 -0
  38. tsdb_sql_tool-0.1.0/htmlcov/z_df7d085f4a86470d_exceptions_py.html +138 -0
  39. tsdb_sql_tool-0.1.0/htmlcov/z_df7d085f4a86470d_exit_codes_py.html +116 -0
  40. tsdb_sql_tool-0.1.0/htmlcov/z_df7d085f4a86470d_logging_py.html +149 -0
  41. tsdb_sql_tool-0.1.0/htmlcov/z_df7d085f4a86470d_models_py.html +127 -0
  42. tsdb_sql_tool-0.1.0/htmlcov/z_df7d085f4a86470d_monitoring_py.html +119 -0
  43. tsdb_sql_tool-0.1.0/htmlcov/z_df7d085f4a86470d_postgres_py.html +607 -0
  44. tsdb_sql_tool-0.1.0/htmlcov/z_df7d085f4a86470d_query_source_py.html +140 -0
  45. tsdb_sql_tool-0.1.0/htmlcov/z_df7d085f4a86470d_timescaledb_py.html +587 -0
  46. tsdb_sql_tool-0.1.0/pyproject.toml +158 -0
  47. tsdb_sql_tool-0.1.0/src/sql_tool/__about__.py +1 -0
  48. tsdb_sql_tool-0.1.0/src/sql_tool/__init__.py +5 -0
  49. tsdb_sql_tool-0.1.0/src/sql_tool/__main__.py +6 -0
  50. tsdb_sql_tool-0.1.0/src/sql_tool/cli/__init__.py +0 -0
  51. tsdb_sql_tool-0.1.0/src/sql_tool/cli/commands/__init__.py +0 -0
  52. tsdb_sql_tool-0.1.0/src/sql_tool/cli/commands/_shared.py +125 -0
  53. tsdb_sql_tool-0.1.0/src/sql_tool/cli/commands/config.py +118 -0
  54. tsdb_sql_tool-0.1.0/src/sql_tool/cli/commands/query.py +35 -0
  55. tsdb_sql_tool-0.1.0/src/sql_tool/cli/commands/service.py +94 -0
  56. tsdb_sql_tool-0.1.0/src/sql_tool/cli/commands/ts.py +1019 -0
  57. tsdb_sql_tool-0.1.0/src/sql_tool/cli/helpers.py +121 -0
  58. tsdb_sql_tool-0.1.0/src/sql_tool/cli/main.py +924 -0
  59. tsdb_sql_tool-0.1.0/src/sql_tool/cli/output.py +64 -0
  60. tsdb_sql_tool-0.1.0/src/sql_tool/core/__init__.py +0 -0
  61. tsdb_sql_tool-0.1.0/src/sql_tool/core/client.py +133 -0
  62. tsdb_sql_tool-0.1.0/src/sql_tool/core/config.py +278 -0
  63. tsdb_sql_tool-0.1.0/src/sql_tool/core/exceptions.py +41 -0
  64. tsdb_sql_tool-0.1.0/src/sql_tool/core/exit_codes.py +19 -0
  65. tsdb_sql_tool-0.1.0/src/sql_tool/core/logging.py +52 -0
  66. tsdb_sql_tool-0.1.0/src/sql_tool/core/models.py +30 -0
  67. tsdb_sql_tool-0.1.0/src/sql_tool/core/monitoring.py +22 -0
  68. tsdb_sql_tool-0.1.0/src/sql_tool/core/postgres.py +510 -0
  69. tsdb_sql_tool-0.1.0/src/sql_tool/core/query_source.py +43 -0
  70. tsdb_sql_tool-0.1.0/src/sql_tool/core/timescaledb.py +490 -0
  71. tsdb_sql_tool-0.1.0/src/sql_tool/formatters/__init__.py +6 -0
  72. tsdb_sql_tool-0.1.0/src/sql_tool/formatters/base.py +54 -0
  73. tsdb_sql_tool-0.1.0/src/sql_tool/formatters/csv.py +36 -0
  74. tsdb_sql_tool-0.1.0/src/sql_tool/formatters/json.py +41 -0
  75. tsdb_sql_tool-0.1.0/src/sql_tool/formatters/table.py +53 -0
  76. tsdb_sql_tool-0.1.0/tests/__init__.py +0 -0
  77. tsdb_sql_tool-0.1.0/tests/cli/__init__.py +0 -0
  78. tsdb_sql_tool-0.1.0/tests/cli/test_e2e_formatting.py +304 -0
  79. tsdb_sql_tool-0.1.0/tests/cli/test_exit_codes.py +119 -0
  80. tsdb_sql_tool-0.1.0/tests/cli/test_main.py +187 -0
  81. tsdb_sql_tool-0.1.0/tests/cli/test_output.py +93 -0
  82. tsdb_sql_tool-0.1.0/tests/cli/test_pg.py +416 -0
  83. tsdb_sql_tool-0.1.0/tests/cli/test_query.py +191 -0
  84. tsdb_sql_tool-0.1.0/tests/cli/test_ts.py +719 -0
  85. tsdb_sql_tool-0.1.0/tests/conftest.py +32 -0
  86. tsdb_sql_tool-0.1.0/tests/core/__init__.py +0 -0
  87. tsdb_sql_tool-0.1.0/tests/fixtures/magnum_sample.sql +4 -0
  88. tsdb_sql_tool-0.1.0/tests/fixtures/multi_row.sql +2 -0
  89. tsdb_sql_tool-0.1.0/tests/fixtures/select_42.sql +1 -0
  90. tsdb_sql_tool-0.1.0/tests/fixtures/simple_query.sql +1 -0
  91. tsdb_sql_tool-0.1.0/tests/formatters/__init__.py +0 -0
  92. tsdb_sql_tool-0.1.0/tests/formatters/test_base.py +97 -0
  93. tsdb_sql_tool-0.1.0/tests/formatters/test_csv.py +98 -0
  94. tsdb_sql_tool-0.1.0/tests/formatters/test_json.py +110 -0
  95. tsdb_sql_tool-0.1.0/tests/formatters/test_table.py +95 -0
  96. tsdb_sql_tool-0.1.0/tests/integration/__init__.py +0 -0
  97. tsdb_sql_tool-0.1.0/tests/integration_config.py +36 -0
  98. tsdb_sql_tool-0.1.0/tests/test_client.py +165 -0
  99. tsdb_sql_tool-0.1.0/tests/test_config.py +950 -0
  100. tsdb_sql_tool-0.1.0/tests/test_exceptions.py +104 -0
  101. tsdb_sql_tool-0.1.0/tests/test_helpers.py +287 -0
  102. tsdb_sql_tool-0.1.0/tests/test_logging.py +47 -0
  103. tsdb_sql_tool-0.1.0/tests/test_models.py +95 -0
  104. tsdb_sql_tool-0.1.0/tests/test_package.py +40 -0
  105. tsdb_sql_tool-0.1.0/tests/test_postgres.py +522 -0
  106. tsdb_sql_tool-0.1.0/tests/test_query_source.py +77 -0
  107. tsdb_sql_tool-0.1.0/tests/test_timescaledb.py +288 -0
  108. tsdb_sql_tool-0.1.0/uv.lock +694 -0
Binary file
@@ -0,0 +1,5 @@
1
+ export SQL_TOOL_TEST_PROFILE=piccolo_dev_magnum
2
+ export SQL_TOOL_TEST_SCHEMA=magnum
3
+ export SQL_TOOL_TEST_TABLE=magnum_data
4
+ export SQL_TOOL_TEST_DATABASE=piccolo_dev
5
+ export SQL_TOOL_TEST_PLAIN_TABLE=flyway_schema_history
@@ -0,0 +1,134 @@
1
+ # Contributing to sql-tool
2
+
3
+ ## Development Setup
4
+
5
+ ### Prerequisites
6
+
7
+ - Python 3.13+
8
+ - [uv](https://docs.astral.sh/uv/) (package manager)
9
+ - PostgreSQL 15+ (for integration tests)
10
+ - TimescaleDB extension (optional, for TimescaleDB command tests)
11
+
12
+ ### Install Dependencies
13
+
14
+ ```bash
15
+ git clone https://github.com/vladistan/sql-tool.git
16
+ cd sql-tool
17
+ uv sync --all-extras
18
+ ```
19
+
20
+ ### Configure a Test Database Profile
21
+
22
+ Integration tests require a running PostgreSQL instance. Create a config file at `~/.config/sql-tool/config.toml`:
23
+
24
+ ```toml
25
+ [profiles.test_db]
26
+ host = "localhost"
27
+ port = 5432
28
+ dbname = "postgres"
29
+ user = "postgres"
30
+ password = "your_password"
31
+ default_schema = "public"
32
+ ```
33
+
34
+ See `config.example.toml` for more configuration options including DSN-style connections.
35
+
36
+ ### Integration Test Environment Variables
37
+
38
+ Integration tests use environment variables to locate your test database objects. Set these to match your local setup:
39
+
40
+ ```bash
41
+ export SQL_TOOL_TEST_PROFILE=test_db # Config profile name
42
+ export SQL_TOOL_TEST_SCHEMA=public # Schema with test tables
43
+ export SQL_TOOL_TEST_TABLE=my_hypertable # A TimescaleDB hypertable
44
+ export SQL_TOOL_TEST_DATABASE=postgres # Database name
45
+ export SQL_TOOL_TEST_PLAIN_TABLE=some_regular_table # A non-hypertable table
46
+ ```
47
+
48
+ If not set, tests use generic defaults (`myschema`, `sensor_data`, etc.) that you would need to create in your database.
49
+
50
+ ## Development Workflow
51
+
52
+ ### Running Tests
53
+
54
+ ```bash
55
+ # All tests
56
+ uv run pytest
57
+
58
+ # Unit tests only (no database required)
59
+ uv run pytest -m unit
60
+
61
+ # Integration tests only (requires PostgreSQL)
62
+ uv run pytest -m integration
63
+
64
+ # Skip slow tests
65
+ uv run pytest -m "not slow"
66
+ ```
67
+
68
+ ### Linting
69
+
70
+ ```bash
71
+ # Check for issues
72
+ uv run ruff check src/ tests/
73
+
74
+ # Auto-fix issues
75
+ uv run ruff check --fix src/ tests/
76
+
77
+ # Format code
78
+ uv run ruff format src/ tests/
79
+ ```
80
+
81
+ ### Type Checking
82
+
83
+ ```bash
84
+ uv run mypy src/
85
+ ```
86
+
87
+ ### Pre-commit Hooks
88
+
89
+ ```bash
90
+ uv run pre-commit install
91
+ uv run pre-commit run --all-files
92
+ ```
93
+
94
+ ## Code Style
95
+
96
+ - Line length: 88 characters
97
+ - Formatting: ruff (Black-compatible)
98
+ - Import sorting: ruff isort
99
+ - Type annotations: required for all public functions (mypy strict mode)
100
+ - Test coverage: minimum 80%
101
+
102
+ ## Project Structure
103
+
104
+ ```
105
+ src/sql_tool/
106
+ ├── cli/ # CLI commands (typer)
107
+ │ ├── commands/ # Subcommand groups (pg, ts, query)
108
+ │ ├── helpers.py # CLI utilities
109
+ │ ├── main.py # Entry point
110
+ │ └── output.py # Output formatting
111
+ ├── core/ # Core logic
112
+ │ ├── client.py # PostgreSQL client
113
+ │ ├── config.py # Configuration loading
114
+ │ ├── models.py # Data models
115
+ │ ├── postgres.py # PostgreSQL admin queries
116
+ │ └── timescaledb.py # TimescaleDB admin queries
117
+ └── formatters/ # Output formatters (table, json, csv)
118
+
119
+ tests/
120
+ ├── cli/ # CLI integration tests
121
+ ├── fixtures/ # SQL fixtures
122
+ ├── test_client.py
123
+ ├── test_config.py
124
+ └── ...
125
+ ```
126
+
127
+ ## Submitting Changes
128
+
129
+ 1. Fork the repository
130
+ 2. Create a feature branch (`git checkout -b feature/my-change`)
131
+ 3. Make your changes
132
+ 4. Run the full check suite: `uv run ruff check src/ tests/ && uv run mypy src/ && uv run pytest`
133
+ 5. Commit with a descriptive message
134
+ 6. Open a pull request
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Vlad Korolev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,309 @@
1
+ Metadata-Version: 2.4
2
+ Name: tsdb-sql-tool
3
+ Version: 0.1.0
4
+ Summary: PostgreSQL query and administration CLI tool
5
+ Project-URL: Homepage, https://github.com/vladistan/sql-tool
6
+ Project-URL: Repository, https://github.com/vladistan/sql-tool
7
+ Project-URL: Issues, https://github.com/vladistan/sql-tool/issues
8
+ Author-email: Vlad Korolev <vlad@v-lad.org>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: admin,cli,database,postgresql,sql,timescaledb
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: System Administrators
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Database
20
+ Classifier: Topic :: System :: Systems Administration
21
+ Requires-Python: >=3.13
22
+ Requires-Dist: psycopg[binary]>=3.1.0
23
+ Requires-Dist: pydantic>=2.5.0
24
+ Requires-Dist: rich>=13.0.0
25
+ Requires-Dist: sentry-sdk>=1.40.0
26
+ Requires-Dist: structlog>=24.0
27
+ Requires-Dist: typer>=0.12.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: mypy>=1.13; extra == 'dev'
30
+ Requires-Dist: pre-commit>=4.0; extra == 'dev'
31
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
32
+ Requires-Dist: pytest>=8.0; extra == 'dev'
33
+ Requires-Dist: ruff>=0.8; extra == 'dev'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # sql-tool
37
+
38
+ PostgreSQL and TimescaleDB query and administration CLI tool.
39
+
40
+ Provides multiple output formats (table, JSON, CSV), flexible connection management (CLI flags, DSN, PG* env vars, config profiles), and admin commands for database inspection and maintenance.
41
+
42
+ ## Installation
43
+
44
+ ```bash
45
+ git clone <repository-url>
46
+ cd sql-tool
47
+ uv sync
48
+ ```
49
+
50
+ Run commands with `uv run sql-tool` or install globally:
51
+
52
+ ```bash
53
+ uv tool install .
54
+ ```
55
+
56
+ ## Quick Start
57
+
58
+ ```bash
59
+ # Check connectivity
60
+ sql-tool service check
61
+
62
+ # Run a query
63
+ sql-tool query -e "SELECT now()"
64
+
65
+ # List databases
66
+ sql-tool databases
67
+
68
+ # List tables in a schema
69
+ sql-tool -s myschema table
70
+
71
+ # Show table columns and preview data
72
+ sql-tool table myschema.sensor_data --head 5
73
+ ```
74
+
75
+ ## Commands
76
+
77
+ ### Query Execution
78
+
79
+ ```bash
80
+ # Inline query
81
+ sql-tool query -e "SELECT * FROM users LIMIT 10"
82
+
83
+ # From file
84
+ sql-tool query queries/report.sql
85
+
86
+ # From stdin
87
+ echo "SELECT 1" | sql-tool query
88
+
89
+ # With timeout
90
+ sql-tool query -e "SELECT pg_sleep(5)" -t 3
91
+ ```
92
+
93
+ ### Database Overview
94
+
95
+ ```bash
96
+ # List all databases (sorted by size)
97
+ sql-tool databases
98
+
99
+ # List schemas with space usage
100
+ sql-tool schema
101
+
102
+ # Schemas across all databases
103
+ sql-tool schema --all-databases
104
+ ```
105
+
106
+ ### Table Inspection
107
+
108
+ ```bash
109
+ # List all tables with sizes
110
+ sql-tool table
111
+
112
+ # Filter by schema
113
+ sql-tool -s myschema table
114
+
115
+ # Show column definitions
116
+ sql-tool table myschema.sensor_data
117
+
118
+ # Preview data
119
+ sql-tool table myschema.sensor_data --head 10
120
+ sql-tool table myschema.sensor_data --tail 5
121
+ sql-tool table myschema.sensor_data --sample 3
122
+
123
+ # Show timestamp range for hypertables
124
+ sql-tool table myschema.sensor_data --range
125
+ ```
126
+
127
+ ### Connections
128
+
129
+ ```bash
130
+ # Active connections (non-idle)
131
+ sql-tool connections
132
+
133
+ # All connections including idle
134
+ sql-tool connections --all
135
+
136
+ # Connection summary with memory config
137
+ sql-tool connections --summary
138
+
139
+ # Filter by user, database, or state
140
+ sql-tool connections --filter-user appuser --filter-db mydb
141
+ sql-tool connections --min-duration 5
142
+ ```
143
+
144
+ ### Service & Maintenance
145
+
146
+ ```bash
147
+ # Check server connectivity and version
148
+ sql-tool service check
149
+
150
+ # Vacuum a table
151
+ sql-tool service vacuum my_table
152
+ sql-tool service vacuum my_table --full
153
+ sql-tool service vacuum --all
154
+
155
+ # Kill a backend process
156
+ sql-tool service kill 12345
157
+ sql-tool service kill 12345 --cancel # cancel query only
158
+ ```
159
+
160
+ ### TimescaleDB
161
+
162
+ ```bash
163
+ # List hypertables
164
+ sql-tool ts hypertables
165
+
166
+ # Show chunks for a hypertable
167
+ sql-tool ts chunks myschema.sensor_data
168
+
169
+ # Compression statistics
170
+ sql-tool ts compression
171
+ sql-tool ts compression myschema.sensor_data
172
+
173
+ # Compression settings and policies
174
+ sql-tool ts compression-settings -s myschema
175
+
176
+ # Configure compression
177
+ sql-tool ts compression-set myschema.sensor_data --segmentby "device_id, sensor" --orderby "timestamp DESC"
178
+ sql-tool ts compression-set myschema.sensor_data --policy "4 hours"
179
+
180
+ # Compress chunks
181
+ sql-tool ts compress myschema.sensor_data
182
+ sql-tool ts compress myschema.sensor_data --chunk 11420
183
+
184
+ # Continuous aggregates
185
+ sql-tool ts caggs
186
+
187
+ # Retention policies
188
+ sql-tool ts retention
189
+
190
+ # Background jobs
191
+ sql-tool ts jobs
192
+ sql-tool ts jobs --history
193
+ sql-tool ts jobs --history --job 1005
194
+ ```
195
+
196
+ ### Configuration
197
+
198
+ ```bash
199
+ # Show resolved config with source attribution
200
+ sql-tool config show
201
+
202
+ # List available profiles
203
+ sql-tool config profiles
204
+ ```
205
+
206
+ ## Output Formats
207
+
208
+ All listing commands support multiple output formats:
209
+
210
+ ```bash
211
+ # Table format (default in terminal)
212
+ sql-tool -f table databases
213
+
214
+ # JSON format
215
+ sql-tool -f json databases
216
+
217
+ # Compact JSON
218
+ sql-tool --compact -f json databases
219
+
220
+ # CSV format (default when piped)
221
+ sql-tool databases | head
222
+
223
+ # CSV without header
224
+ sql-tool --no-header databases
225
+ ```
226
+
227
+ Auto-detection: table format for TTY, CSV when piped.
228
+
229
+ ## Connection Options
230
+
231
+ Global flags (must appear before the subcommand):
232
+
233
+ ```bash
234
+ sql-tool -H myhost -p 5432 -d mydb -U myuser query -e "SELECT 1"
235
+ sql-tool --dsn "postgresql://user@host/db" databases
236
+ sql-tool -P production table
237
+ ```
238
+
239
+ | Flag | Env Var | Description |
240
+ |------|---------|-------------|
241
+ | `-H, --host` | `PGHOST` | PostgreSQL host |
242
+ | `-p, --port` | `PGPORT` | PostgreSQL port |
243
+ | `-d, --database` | `PGDATABASE` | Database name |
244
+ | `-U, --user` | `PGUSER` | User name |
245
+ | `-W, --password` | `PGPASSWORD` | Password |
246
+ | `--dsn` | | Connection DSN |
247
+ | `-P, --profile` | `SQL_PROFILE` | Named profile |
248
+
249
+ ## Configuration File
250
+
251
+ Location: `~/.config/sql-tool/config.toml`
252
+
253
+ ```toml
254
+ default_timeout = 30
255
+ default_format = "table"
256
+
257
+ [profiles.local]
258
+ host = "localhost"
259
+ port = 5432
260
+ dbname = "postgres"
261
+ user = "postgres"
262
+
263
+ [profiles.production]
264
+ dsn = "postgresql://readonly@prod-db.example.com:5432/myapp?sslmode=verify-full"
265
+
266
+ [profiles.staging]
267
+ dsn = "postgresql://user@staging-db.example.com/myapp"
268
+ sslmode = "verify-full"
269
+ connect_timeout = 5
270
+ ```
271
+
272
+ See `config.example.toml` for a full example.
273
+
274
+ ### Precedence (highest to lowest)
275
+
276
+ 1. CLI flags (`--host`, `--port`, etc.)
277
+ 2. `--dsn` flag
278
+ 3. Environment variables (`PGHOST`, `PGPORT`, etc.)
279
+ 4. Named profile (`--profile` or `SQL_PROFILE`)
280
+ 5. Config file defaults
281
+ 6. Built-in defaults (`localhost:5432/postgres`)
282
+
283
+ ## Exit Codes
284
+
285
+ | Code | Meaning |
286
+ |------|---------|
287
+ | 0 | Success |
288
+ | 1 | General error (SQL syntax, permission denied) |
289
+ | 2 | Usage error (invalid arguments) |
290
+ | 3 | Input error (file not found, invalid parameters) |
291
+ | 5 | Network error (connection failed, authentication) |
292
+ | 6 | Timeout (query timeout, connection timeout) |
293
+ | 7 | Configuration error (malformed config, unknown profile) |
294
+
295
+ ## Development
296
+
297
+ ```bash
298
+ # Run tests
299
+ uv run pytest
300
+
301
+ # Run with coverage
302
+ uv run pytest --cov=sql_tool
303
+
304
+ # Lint
305
+ uv run ruff check src/
306
+
307
+ # Type check
308
+ uv run mypy src/
309
+ ```