# safenames

> Modify headers of a CSV to only have ["safe" names](../../src/cmd/safenames.rs#L5-L14) - guaranteed "database-ready"/"CKAN-ready" names.

**[Table of Contents](TableOfContents.md)** | **Source: [src/cmd/safenames.rs](https://github.com/dathere/qsv/blob/master/src/cmd/safenames.rs)** | [![CKAN](../images/ckan.png)](TableOfContents.md#legend "has CKAN-aware integration options.")

<a name="nav"></a>
[Description](#description) | [Usage](#usage) | [Safenames Options](#safenames-options) | [Common Options](#common-options)

<a name="description"></a>

## Description [↩](#nav)

Modify headers of a CSV to only have "safe" names - guaranteed "database-ready" names
(optimized specifically for PostgreSQL column identifiers).

Fold to lowercase. Trim leading & trailing whitespaces. Replace whitespace/non-alphanumeric
characters with _. If name starts with a number & check_first_char is true, prepend the unsafe prefix.
If a header with the same name already exists, append a sequence suffix (e.g. col, col_2, col_3).
Names are limited to 60 bytes in length (snapped to UTF-8 char boundary, including any
duplicate-disambiguation suffix). Empty names are replaced with the unsafe prefix.

In addition, specifically because of CKAN Datastore requirements:  
- Headers with leading underscores are replaced with "unsafe_" prefix.
- Headers that are named "_id" are renamed to "reserved__id".

These CKAN Datastore options can be configured via the --prefix & --reserved options, respectively.

In Always (a) and Conditional (c) mode, returns number of modified headers to stderr,
and sends CSV with safe headers output to stdout.

In Verify (v) mode, returns number of unsafe headers to stderr.
In Verbose (V) mode, returns number of headers; duplicate count and unsafe & safe headers to stderr.
No stdout output is generated in Verify and Verbose mode.

In JSON (j) mode, returns Verbose mode info in minified JSON to stdout.
In Pretty JSON (J) mode, returns Verbose mode info in pretty printed JSON to stdout.

Given data.csv:  
c1,12_col,Col with Embedded Spaces,,Column!@Invalid+Chars,c1
1,a2,a3,a4,a5,a6

```console
$ qsv safenames data.csv
```

c1,unsafe_12_col,col_with_embedded_spaces,unsafe_,column__invalid_chars,c1_2
1,a2,a3,a4,a5,a6
stderr: 5

Conditionally rename headers, allowing "quoted identifiers":  
```console
$ qsv safenames --mode c data.csv
```

c1,unsafe_12_col,Col with Embedded Spaces,unsafe_,column__invalid_chars,c1_2
1,a2,a3,a4,a5,a6
stderr: 4

Verify how many "unsafe" headers are found:  
```console
$ qsv safenames --mode v data.csv
```

stderr: 4

Verbose mode:  
```console
$ qsv safenames --mode V data.csv
```

stderr: 6 header/s
1 duplicate/s: "c1:2"
4 unsafe header/s: ["12_col", "Col with Embedded Spaces", "", "Column!@Invalid+Chars"]
1 safe header/s: ["c1"]

"Safer" (s) mode - like always, but collapses runs of non-alphanumeric
characters into a single _ (note "column_invalid_chars", not "column__invalid_chars"):  
```console
$ qsv safenames --mode s data.csv
```

c1,unsafe_12_col,col_with_embedded_spaces,unsafe_,column_invalid_chars,c1_2
1,a2,a3,a4,a5,a6
stderr: 5

"Safer" with unicode (S) mode - same as s, but preserves unicode letters & numbers.
Given a header "Café #5", "--mode S" yields "café_5", whereas the ASCII
"--mode s" strips the accent, yielding "caf_5":  
```console
$ qsv safenames --mode S data.csv
```


The --collapse & --unicode flags can be combined with ANY mode, including the
verify & JSON modes, so the report reflects the "safer" rewrite:  
```console
$ qsv safenames --mode j --collapse --unicode data.csv
```


Note that even if "Col with Embedded Spaces" is technically safe, it is generally discouraged.
Though it can be created as a "quoted identifier" in PostgreSQL, it is still marked "unsafe"
by default, unless mode is set to "conditional."

It is discouraged because the embedded spaces can cause problems later on.
(see <https://lerner.co.il/2013/11/30/quoting-postgresql/> for more info).

For more examples, see <https://github.com/dathere/qsv/blob/master/tests/test_safenames.rs>.
See also <https://github.com/dathere/qsv/wiki/Transform-and-Reshape#safenames>


<a name="usage"></a>

## Usage [↩](#nav)

```console
qsv safenames [options] [<input>]
qsv safenames --help
```

<a name="safenames-options"></a>

## Safenames Options [↩](#nav)

| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Option&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Type | Description | Default |
|--------|------|-------------|--------|
| &nbsp;`‑‑mode`&nbsp; | string | Rename header names to "safe" names — guaranteed "database-ready" names. Mode is selected by the FIRST character: c/C conditional, a/A always, s safer, S Safer (unicode), v verify, V Verbose, j JSON, J pretty JSON (case matters for s vs S, v vs V and j vs J; --mode verbose maps to 'v', NOT V). | `Always` |
| &nbsp;`‑‑reserved`&nbsp; | string | Comma-delimited list of additional case-insensitive reserved names that should be considered "unsafe." If a header name is found in the reserved list, it will be prefixed with "reserved_". | `_id` |
| &nbsp;`‑‑prefix`&nbsp; | string | Certain systems do not allow header names to start with "_" (e.g. CKAN Datastore). This option allows the specification of the unsafe prefix to use when a header starts with "_". | `unsafe_` |
| &nbsp;`‑‑collapse`&nbsp; | flag | Collapse consecutive runs of non-alphanumeric characters into a single _. Composes with ALL modes (including verify & JSON modes). Implied by --mode s and --mode S. |  |
| &nbsp;`‑‑unicode`&nbsp; | flag | Preserve unicode letters & numbers instead of stripping to ASCII. Composes with ALL modes (including verify & JSON modes). Implied by --mode S. |  |

<a name="common-options"></a>

## Common Options [↩](#nav)

| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Option&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Type | Description | Default |
|--------|------|-------------|--------|
| &nbsp;`‑h,`<br>`‑‑help`&nbsp; | flag | Display this message |  |
| &nbsp;`‑o,`<br>`‑‑output`&nbsp; | string | Write output to <file> instead of stdout. Note that no output is generated for Verify and Verbose modes. |  |
| &nbsp;`‑d,`<br>`‑‑delimiter`&nbsp; | string | The field delimiter for reading CSV data. Must be a single character. (default: ,) |  |

---
**Source:** [`src/cmd/safenames.rs`](https://github.com/dathere/qsv/blob/master/src/cmd/safenames.rs)
| **[Table of Contents](TableOfContents.md)** | **[README](../../README.md)**
