@saptools/cf-hana 0.3.5 → 0.4.1

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  <!-- cspell:words VARCHAR -->
4
4
 
5
+ ## 0.4.0 - 2026-07-14
6
+
7
+ - Back up `REPLACE` and matched `MERGE INTO` pre-images, cap backup size, and
8
+ refuse those statements when their target or safe pre-image cannot be derived.
9
+ - Confirm every resolved CLI target on stderr, distinguish ambient from explicit
10
+ selectors, and verify direct `cf env` identity against the ambient target.
11
+ - Add actionable insufficient-privilege guidance with schema, technical user,
12
+ current binding, and sibling binding names without automatic retries.
13
+ - Auto-save exact rows only when compact CSV shortens cells, add
14
+ `--no-auto-save`, and make implicit storage failures non-fatal.
15
+ - Add lossless `query --format table|json|json-compact|csv`, flat catalog name
16
+ output, and exact per-command JSON schemas in help while preserving defaults.
17
+ - Scope metadata suggestions by binding identity and document the existing
18
+ bounded CF retries and 60-second timeout defaults.
19
+
5
20
  ## 0.3.5 - 2026-07-06
6
21
 
7
22
  - Normalize HANA `BOOLEAN` result columns that arrive from the driver as `1`/`0`
package/README.md CHANGED
@@ -11,6 +11,8 @@ password re-authentication.
11
11
  ## Features
12
12
 
13
13
  - **Selector-based connect** — `region/org/space/app` or a bare app name.
14
+ - **Visible target provenance** — every connecting CLI command confirms the
15
+ resolved selector on stderr and labels ambient versus explicit targeting.
14
16
  - **Credentials, handled for you** — HANA bindings are read live from Cloud Foundry.
15
17
  Bare app names use the current CF session first; explicit selectors use isolated live authentication.
16
18
  - **Parameterized queries** — values always travel as bound `?` parameters, never
@@ -21,14 +23,18 @@ password re-authentication.
21
23
  `deleteFrom` — query a table by name without writing SQL.
22
24
  - **Schema introspection** — list schemas, tables, and columns.
23
25
  - **Table-name recovery** — failed CLI queries for missing tables/views show nearby schema-local suggestions on stderr.
26
+ - **Privilege recovery** — HANA error 258 identifies the active schema,
27
+ technical user, binding, and any sibling bindings worth trying explicitly.
24
28
  - **Local SQL history** — direct SQL calls are appended to dated JSONL files
25
29
  under `~/.saptools/cf-hana/histories/` with five-day retention.
26
- - **Write backups** — CLI `UPDATE`, `UPSERT`, and `DELETE` statements create a local CSV
27
- backup of matching rows before the write runs.
30
+ - **Write backups** — CLI `UPDATE`, `UPSERT`, `REPLACE`, matched `MERGE`, and
31
+ `DELETE` statements preserve pre-image rows before the write runs.
28
32
  - **Compact CLI results** — CLI `SELECT`/`WITH` output is compact CSV with
29
- bounded cells and optional saved refs for exact follow-up inspection.
33
+ bounded cells; truncated exact values are retained automatically for follow-up inspection.
34
+ - **Lossless CLI formats** — `query --format table|json|json-compact|csv`
35
+ provides exact cell values without changing the compact-CSV default.
30
36
  - **Safety guard** — opt-in read-only mode and a destructive-statement guard
31
- (blocks `DROP`/`TRUNCATE`/`ALTER` and unscoped `UPDATE`/`DELETE`).
37
+ (blocks destructive DDL, unscoped `UPDATE`/`DELETE`, and unconditional matched deletes).
32
38
  - **Typed results** — `query<TRow>()` returns typed rows.
33
39
  - **CLI + API** — a `cf-hana` CLI and an ergonomic TypeScript API.
34
40
 
@@ -76,6 +82,15 @@ Every entry point takes a selector as its first argument:
76
82
  (current org/space/API endpoint) and fetched with `cf env app-demo` using your
77
83
  existing CF session before any isolated re-auth fallback.
78
84
 
85
+ Every connecting CLI command prints the resolved selector to stderr. A bare
86
+ selector is labeled as inherited from ambient `cf target`; an explicit selector
87
+ is labeled as pinned. For the direct bare-app path, cf-hana verifies the app,
88
+ API, org, and space embedded in the same `VCAP_APPLICATION` payload as the
89
+ bindings, then reads `cf target` again. Missing or mismatched identity, including
90
+ an A-to-B-to-A target race, is refused before a database connection is opened.
91
+ If the ambient API cannot be mapped to a supported region, the notice says the
92
+ region is unconfirmed instead of presenting `current/...` as a usable pin.
93
+
79
94
  ## CLI
80
95
 
81
96
  ```
@@ -91,10 +106,11 @@ cf-hana result <command> Inspect saved query refs
91
106
  Common options: `--refresh` (deprecated compatibility flag; binding discovery is already live), `--role <runtime|hdi>`, `--binding <name>` /
92
107
  `--binding-index <n>`, `--timeout <ms>`, `--read-only`, `--allow-destructive`,
93
108
  `--limit <n>`, `--no-auto-limit`. The `query` command also accepts
94
- `--param <value>` (repeatable), `--cell-limit <n>`, `--save`,
95
- `--result-ttl-minutes <n>`, and `--refresh-metadata`. `tables` and `columns` still support
96
- `--format <table|json|csv>`. CLI `UPDATE`, `UPSERT`, and `DELETE` statements are backed up
97
- automatically before the write runs.
109
+ `--param <value>` (repeatable), `--cell-limit <n>`, `--save`, `--no-auto-save`,
110
+ `--format <table|json|json-compact|csv>`, `--result-ttl-minutes <n>`, and
111
+ `--refresh-metadata`. `tables` and `columns` support the same four format values.
112
+ CLI `UPDATE`, `UPSERT`, `REPLACE`, matched `MERGE`, and `DELETE` statements are
113
+ backed up automatically before the write runs.
98
114
 
99
115
  ```bash
100
116
  cf-hana query eu10/example-org/space-demo/app-demo "SELECT ID, STATUS FROM ORDERS WHERE STATUS = ?" \
@@ -106,6 +122,27 @@ cf-hana columns app-demo ORDERS_APP.ORDERS
106
122
  cf-hana ping eu10/example-org/space-demo/app-demo
107
123
  ```
108
124
 
125
+ ## Output formats and schemas
126
+
127
+ With no `query --format`, successful `SELECT`/`WITH` output remains compact CSV
128
+ for backward compatibility. An explicit format is lossless at the cell level:
129
+
130
+ - `query --format json` returns `[{COLUMN: value, ...}]`.
131
+ - `query --format json-compact` returns `[value, ...]` for a single-column
132
+ projection and falls back to row objects for multiple columns.
133
+ - `query --format csv` returns lossless RFC 4180 CSV.
134
+ - `query --format table` returns a lossless aligned table.
135
+ - `tables --format json` returns `[{SCHEMA,TABLE,TYPE}]`; its `json-compact`
136
+ mode returns `[TABLE, ...]`.
137
+ - `columns --format json` returns
138
+ `[{COLUMN,TYPE,LENGTH,NULLABLE,POSITION}]`; its `json-compact` mode returns
139
+ `[COLUMN, ...]`.
140
+
141
+ The existing uppercase catalog keys are unchanged. Query formats are available
142
+ only for `SELECT`/`WITH`. `--save` cannot be combined with `--format`, which
143
+ keeps JSON and CSV stdout valid machine output. The automatic row cap still
144
+ applies unless changed with `--limit` or `--no-auto-limit`.
145
+
109
146
  ## Compact query output and saved refs
110
147
 
111
148
  For CLI `SELECT` and `WITH` statements, stdout is CSV. Bare reads return at most
@@ -113,7 +150,14 @@ For CLI `SELECT` and `WITH` statements, stdout is CSV. Bare reads return at most
113
150
  disable the automatic cap. Data cells display at most 128 Unicode characters by
114
151
  default; pass `--cell-limit <n>` to choose a value from 1 through 10,000.
115
152
 
116
- Use `--save` when you need exact values later:
153
+ When compact output actually shortens one or more cells, cf-hana automatically
154
+ saves the exact returned rows and prints a concrete `result show` command with
155
+ the generated ref to stderr. This does not add a `ref=` line to stdout. Disable
156
+ implicit retention with `--no-auto-save`. If an implicit save exceeds the
157
+ 256 MiB store ceiling or local storage is unavailable, the query still succeeds
158
+ and the hint recommends `--save` or a larger `--cell-limit`.
159
+
160
+ Use explicit `--save` when you want a ref regardless of whether cells are shortened:
117
161
 
118
162
  ```bash
119
163
  cf-hana query app-demo "SELECT ID, CONTENT FROM ORDERS" --read-only --save
@@ -145,9 +189,18 @@ cf-hana result prune
145
189
  cf-hana result clear
146
190
  ```
147
191
 
148
- `--save` is available only for `SELECT` and `WITH` statements. The programmatic
149
- API keeps returning full-fidelity `QueryResult` values and does not write result
150
- refs.
192
+ `--save` is available only for `SELECT` and `WITH` statements and remains a
193
+ hard failure if the result cannot be stored. The programmatic API keeps
194
+ returning full-fidelity `QueryResult` values and does not write result refs.
195
+
196
+ ## Insufficient-privilege guidance
197
+
198
+ When HANA reports error code 258, or the equivalent `insufficient privilege`
199
+ message without a numeric code, cf-hana keeps the original failure and exit
200
+ status and adds a stderr hint. The hint identifies the schema, role-selected
201
+ technical user, current binding, and other named HANA bindings already found on
202
+ the app. It suggests an explicit `--binding <name>` or another app/full
203
+ selector. It never retries the SQL automatically under another database user.
151
204
 
152
205
  ## Invalid table/view suggestions and metadata cache
153
206
 
@@ -167,8 +220,9 @@ only schema, object name, and object type under:
167
220
  Metadata cache files are private (`0700` directories, `0600` files), written
168
221
  atomically, and expire after exactly 30 minutes. The cache key is derived from
169
222
  non-secret connection identity: selector, app name, host, active schema, role,
170
- and driver. It does not include passwords, certificates, tokens, SQL parameter
171
- values, result rows, or table data, and malformed cache files are treated as
223
+ driver, and selected binding name/index. It does not include passwords,
224
+ certificates, tokens, SQL parameter values, result rows, or table data, and
225
+ malformed cache files are treated as
172
226
  misses. Pass `--refresh-metadata` to bypass this cache for a query. The legacy
173
227
  `--refresh` flag is accepted for compatibility but does not bypass the metadata
174
228
  cache and is not a credential-cache control because binding discovery is already
@@ -189,6 +243,12 @@ query error and simply omits suggestions.
189
243
  `bindingIndex`, `readOnly`, `allowDestructive`, `autoLimit`, `queryTimeoutMs`,
190
244
  `connectTimeoutMs`, deprecated `refresh`, `pool`.
191
245
 
246
+ `HanaClient.info` additively exposes optional target and binding provenance for
247
+ programmatic checks: `selectorSource`, `regionConfirmed`,
248
+ `selectorCanBePinned`, `bindingName`, `bindingIndex`, and
249
+ `availableBindingNames`. Library connections remain silent; only the CLI writes
250
+ the resolved-target notice to stderr.
251
+
192
252
  ## Credentials
193
253
 
194
254
  Credential discovery is **live-only** and does not read `@saptools/cf-sync`
@@ -198,6 +258,8 @@ snapshots or `~/.saptools/cf-db-bindings.json`.
198
258
  validated API endpoint, and first run `cf env app-demo` with your current CF
199
259
  session. This path does not require `SAP_EMAIL` or `SAP_PASSWORD` while the
200
260
  current session is healthy.
261
+ - A successful direct `cf env` is accepted only if a second `cf target` read
262
+ confirms the same API endpoint, org, and space.
201
263
  - If that direct bare-app call fails with an auth/session error, cf-hana falls
202
264
  back to an isolated temporary `CF_HOME`, runs `cf api <current-endpoint>`,
203
265
  authenticates with `SAP_EMAIL` / `SAP_PASSWORD` (or the programmatic `email` /
@@ -213,6 +275,10 @@ has no credential-cache meaning; binding discovery is already live. Use
213
275
  suggestion metadata cache. Credential resolution writes no binding credentials
214
276
  under `~/.saptools/`.
215
277
 
278
+ Cloud Foundry shell-outs use 60-second bounded timeouts and retry transient
279
+ timeout/network failures. HANA connection and query timeout defaults are also
280
+ 60 seconds unless overridden with `--timeout` or API options.
281
+
216
282
  ## SQL history
217
283
 
218
284
  Successful direct SQL calls are appended to daily JSONL files:
@@ -233,16 +299,27 @@ history.
233
299
 
234
300
  ## Write backups
235
301
 
236
- When `cf-hana query` receives an `UPDATE`, `UPSERT`, or `DELETE`, it first builds and runs a
237
- matching `SELECT`:
302
+ When `cf-hana query` receives a supported write, it first builds and runs a
303
+ pre-image `SELECT`:
238
304
 
239
305
  - `UPDATE <target> SET ... WHERE ...` becomes
240
306
  `SELECT * FROM <target> WHERE ...`.
241
307
  - `UPSERT <target> VALUES ... WHERE ...` becomes
242
308
  `SELECT * FROM <target> WHERE ...`.
309
+ - `REPLACE` follows the same plan as its HANA `UPSERT` synonym.
310
+ - A reliably parsed matched `MERGE INTO` uses a correlated `EXISTS` query for
311
+ the matched target rows. If the target is unambiguous but an exact matched set
312
+ is not, cf-hana backs up the whole target table.
243
313
  - `DELETE FROM <target> WHERE ...` becomes
244
314
  `SELECT * FROM <target> WHERE ...`.
245
315
 
316
+ UPSERT/REPLACE subquery forms use a conservative whole-target pre-image.
317
+ Insert-only MERGE statements need no pre-image. For the supported write forms
318
+ above, cf-hana refuses execution if it cannot identify a trustworthy target,
319
+ derive a safe pre-image, preserve the backup within the 256 MiB ceiling, or
320
+ write the backup files. This refusal cannot be overridden with
321
+ `--allow-destructive`.
322
+
246
323
  The backup is saved before the write runs:
247
324
 
248
325
  ```text
@@ -258,12 +335,15 @@ shape. The companion `.statement.sql` file contains the original write statement
258
335
  and `.json` contains non-secret metadata for auditability. Backup files are not
259
336
  deleted by `cf-hana`; clean them up manually when they are no longer needed. The
260
337
  backup path is printed to stderr so stdout remains parseable.
338
+ Backup directories use mode `0700`; statement, CSV, and metadata files use
339
+ mode `0600`.
261
340
 
262
341
  ## Safety
263
342
 
264
343
  - **Read-only mode** (`readOnly` / `--read-only`) rejects every DML and DDL statement.
265
344
  - **Destructive guard** blocks `DROP` / `TRUNCATE` / `ALTER` and `UPDATE` / `DELETE`
266
- without a `WHERE` clause unless `allowDestructive` / `--allow-destructive` is set.
345
+ without a top-level `WHERE`, plus unconditional matched `MERGE DELETE`, unless
346
+ `allowDestructive` / `--allow-destructive` is set.
267
347
  - **Auto-limit** appends a `LIMIT` to bare `SELECT` statements (default 100);
268
348
  `QueryResult.truncated` reports when it clipped the result. Disable with
269
349
  `autoLimit: false` / `--no-auto-limit`.