How do I quote a database name?

I’ve got to create database from a script:

influx -execute "create database $db_name"

Judging from this, one way is to double quote the string. But escape ", and \ with \ before that. And make sure it has no newlines. Like,

#!/usr/bin/env bash
set -eu

quote() {
    local i=$1
    printf '"%s"\n' "$(
        printf '%s\n' "$i" | sed -E 's/"|\\/\\&/g'
    )"
}

validate() {
    local i=$1
    if [ "$(echo "$i" | wc -l)" != 1 ]; then   # empty or containing a newline
        echo "$0: invalid identifier ($i)" >&2
        exit 1
    fi
}

db_name=$1
validate "$db_name"
influx -execute "create database $(quote "$db_name")"

How does it sound?

I think you would need a couple small changes in your script to make it work.

set -eu

quote() {
    local i=$1
    printf '"%s"\n' "$(
        printf '%s\n' "$i" | sed -E 's/"|\\/\\&/g'
    )"
}

validate() {
    local i=$1
    if [ `echo $i | wc -l | tr -d " " | tr -d "\n"` != "1" ]; then   # empty or containing a newline
        echo "$0: invalid identifier ($i)" >&2
        exit 1
    fi
}

db_name=$1
validate $db_name
influx -execute "create database $(quote "$db_name")"

In other words,

--- 1.sh   2019-02-05 12:48:49.133356808 +0200
+++ 2.sh   2019-02-05 12:48:48.230023454 +0200
@@ -10,12 +10,12 @@
 
 validate() {
     local i=$1
-    if [ "$(echo "$i" | wc -l)" != 1 ]; then   # empty or containing a newline
+    if [ `echo $i | wc -l | tr -d " " | tr -d "\n"` != "1" ]; then   # empty or containing a newline
         echo "$0: invalid identifier ($i)" >&2
         exit 1
     fi
 }
 
 db_name=$1
-validate "$db_name"
+validate $db_name
 influx -execute "create database $(quote "$db_name")"

First, the following script

#!/usr/bin/env bash
set -eu
validate() {
    echo "$1"
}
a='1 2 3'
validate $a

would output 1. So, passing $db_name to validate unquoted makes it validate only the first word.

Second, in validate you must be trying to count words, not lines. But you split lines after you count them, which makes no sense. The correct incantation would be:

if [ `echo "$i" | wc -w` != 1 ]; then   # not one word

Third, judging from the link from the original post (can’t duplicate it here), spaces are allowed in database names.

Am I missing something?

Hi @x-yuri,

You don’t need to go to this much effort :slight_smile:

Bash (> 4.4) can escape this for you. Please try:

export WEIRD_NAME='Ʋ♫¤ú😞☄Ɣ🙀ǽ😟ı😾☱😺l☦øǔ☥!😢😳ȳ🙃ƴ⚉"\\'
echo ${WEIRD_NAME@Q}

If anyone comes here later, zsh has a different syntax:

echo ${WEIRD_NAME:q}

Hi @rawkode,

How do I use it exactly?

$ db_name=d1 && cmd="create database ${db_name@Q}" && echo "$cmd" && influx -execute "$cmd"
create database 'd1'
ERR: error parsing query: found d1, expected identifier at line 1, char 16
Warning: It is possible this error is due to not setting a database.
Please set a database with the command "use <database>".
error parsing query: found d1, expected identifier at line 1, char 16

From what I gather, ${...@Q} always returns single quoted string, and the only replacement it makes is ' -> '\''. Can it really help?

Zsh example script I used for testing:

#/usr/bin/env zsh
set -xe
DB_NAME=$1

influx -execute "CREATE DATABASE ${(qqq)DB_NAME:-q}"

Tested on command line with:

$ zsh main.sh 'my new database "name" is weird'
+main.sh:3> DB_NAME='my new database "name" is weird'
+main.sh:5> influx -execute 'CREATE DATABASE "my new database \"name\" is weird"'

Which was successfully created:

2019-02-06T12:57:37.059560Z	info	Executing query	{"log_id": "0DSd~xFl000", "service": "query", "query": "CREATE DATABASE \"my new database \\\"name\\\" is weird\""}
[httpd] ::1 - - [06/Feb/2019:12:57:37 +0000] "POST /query?chunked=true&db=&epoch=ns&q=CREATE+DATABASE+%22my+new+database+%5C%22name%5C%22+is+weird%22 HTTP/1.1" 200 57 "-" "InfluxDBShell/v1.7.3" c72649be-2a0e-11e9-802e-f218989d3cca 1274