Bug #7092 mysqldump adds quotes when called from shell script
Submitted: 8 Dec 2004 1:25 Modified: 31 Jan 2005 23:20
Reporter: Matthew Lord Email Updates:
Status: Not a Bug Impact on me:
None 
Category:MySQL Server: mysqldump Command-line Client Severity:S2 (Serious)
Version:all OS:Linux (Linux)
Assigned to: Guilhem Bichot CPU Architecture:Any

[8 Dec 2004 1:25] Matthew Lord
Description:
#!/bin/sh

BASE_DUMP_DIR=$1
MYSQL_BIN=/usr/local/mysql-3.23.58-pc-linux-i686/bin
MYSQL_SOCK=/tmp/mysql323.sock
MYSQL_USER=root
MYSQL_DUMP=mysqldump
DUMP_OPTS="--opt --fields-terminated-by='\t' --lines-terminated-by='\n' -S $MYSQL_SOCK -u 
$MYSQL_USER"

echo "Running $MYSQL_DUMP $DUMP_OPTS -T $BASE_DUMP_DIR/test test"

# works fine
# $MYSQL_DUMP --opt --fields-terminated-by='\t' --lines-terminated-by='\n' -S $MYSQL_SOCK -u 
$MYSQL_USER -T $BASE_DUMP_DIR/test test

# exhibits problem
$MYSQL_DUMP $DUMP_OPTS -T $BASE_DUMP_DIR/test test

When this script is invoked this is the statement that mysqld executes:
SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '/tmp/dumptest/for323/dumptest.txt' 
FIELDS  TERMINATED BY '''\t'''  LINES TERMINATED BY '''\n''' FROM `dumptest`

How to repeat:
create table dumptest (fname varchar(50), lname varchar(50));
insert into dumptest values ("matt", "lord"), ("lilu", "lord"), ("sidney", "lord");

Execute the shell script

Suggested fix:
We need to stop the addition of the quotes.  The fact that the echo output looks correct
points toward mysqldump being the cause.
[31 Jan 2005 22:23] Guilhem Bichot
Created this script which is very much based on the provided testcase:
#!/bin/sh

BASE_DUMP_DIR=$1
#MYSQL_BIN=/usr/local/mysql-3.23.58-pc-linux-i686/bin
MYSQL_SOCK=/tmp/mysql.sock
MYSQL_USER=root
MYSQL_DUMP=/m/mysql-4.1-clean/client/mysqldump
DUMP_OPTS="--opt --fields-terminated-by='\t' --lines-terminated-by='\n' -S $MYSQL_SOCK -u $MYSQL_USER"
echo "Running $MYSQL_DUMP $DUMP_OPTS -T $BASE_DUMP_DIR/test test"
rm -f $BASE_DUMP_DIR/test/*
# works fine
$MYSQL_DUMP --opt --fields-terminated-by='\t' --lines-terminated-by='\n' -S $MYSQL_SOCK -u $MYSQL_USER -T $BASE_DUMP_DIR/test test
# exhibits problem
$MYSQL_DUMP $DUMP_OPTS -T $BASE_DUMP_DIR/test test

Both $MYSQL_DUMP calls, tried one after the other, worked fine (both created files in test dir). Used mysqldump of latest 4.1 bk tree.
[31 Jan 2005 22:40] Guilhem Bichot
Sorry, there was a misunderstanding and now I could repeat it.
[31 Jan 2005 23:20] Guilhem Bichot
I'll assume customer is using bash - sh on Linux is usually a symlink to bash.
The problem has nothing to do with mysqldump.

As 'man bash' says:
"Enclosing  characters  in double quotes preserves the literal value of all characters within the quotes".

Consider this bash script:
s1='hi';
echo $s1;
s2="'hi'";
echo $s2;
When executed, it prints:
[guilhem 00:06 ~/tmp] sh ./7092bis
hi
'hi'
This is exactly what happens in the provided shell script:
DUMP_OPTS="--opt --fields-terminated-by='\t' --lines-terminated-by='\n'
-S $MYSQL_SOCK -u
The fact to put a string in "" does some quoting.
Consider this bash script:
BASE_DUMP_DIR=$1
MYSQL_SOCK=/tmp/mysql.sock
MYSQL_USER=root
MYSQL_DUMP=/m/mysql-4.1-clean/client/mysqldump
DUMP_OPTS="--opt --fields-terminated-by='\t' --lines-terminated-by='\n' -S $MYSQL_SOCK -u $MYSQL_USER"
echo $MYSQL_DUMP --opt --fields-terminated-by='\t' --lines-terminated-by='\n' -S $MYSQL_SOCK -u $MYSQL_USER -T $BASE_DUMP_DIR/test test
echo $MYSQL_DUMP $DUMP_OPTS -T $BASE_DUMP_DIR/test test
(which does not call mysqldump, only echo), it prints:
[guilhem 00:11 ~/tmp] sh ./7092bis
/m/mysql-4.1-clean/client/mysqldump --opt --fields-terminated-by=\t --lines-terminated-by=\n -S /tmp/mysql.sock -u root -T /test test
/m/mysql-4.1-clean/client/mysqldump --opt --fields-terminated-by='\t' --lines-terminated-by='\n' -S /tmp/mysql.sock -u root -T /test test

Again, "'\t'" (which is what DUMP_OPTS is, if we simplify) is not the same as '\t';
"'\t'" means:
" ["] is the string delimiter, treat  ['] as a normal character"
so ['] is passed down to program (echo or mysqldump).
Whereas in '\t' the ['] is the string delimiter, so is not passed down to program (echo or mysqldump).

The customer may want to change his script to:
DUMP_OPTS="--opt --fields-terminated-by=\t --lines-terminated-by=\n -S $MYSQL_SOCK -u $MYSQL_USER"
(removing the [']).