0

I have a strange problem - possibly I'm just going blind. I have this short script, which replaces the string #qry# in the here-document with a select statement in a file and then pipes it to mysql:

#!/bin/bash

if [[ "$1" == "-h" ]]
then
  echo "sqljob [sqlfile] [procnm] [host] [database] [config file]"
  echo "       sqlfile: text file containing an SQL statement"
  echo "       procnm: name that will given to the new, stored procedure"
  echo "       host: hostname of IP address of the database server"
  echo "       database: the procedure will be created here"
  echo "       config file: default configuration file with username and password"
  exit
fi

infile=$1
procnm=$2
hn=$3
pn=$4
db=$5
mycfg=$6

{
set -o noglob
sed -e "s/#qry#/$(echo $(cat $infile))/g" <<!
drop procedure if exists $procnm;
delete from jobs where jobname="$procnm";

insert into jobs
set
  notes="SQL job $procnm",
  jobname="$procnm",
  parm_tmpl='int';

delimiter //
create procedure $procnm(vqid int)
begin
  call joblogmsg(vqid,0,"$procnm","","Executing #qry#");
  drop table if exists ${procnm}_res;
  create table ${procnm}_res as
  #qry#
end//
delimiter ;
!
} | mysql --defaults-file=$mycfg -h $hn -P $pn $db

However, when the select contains *, it expands to whatever is in the directory even though I use noglob. However, it works from the command line:

$ set -o noglob
$ ls *

What am I doing wrong?

Edit

Block Comments in a Shell Script has been suggested as a duplicate, but as you will notice, I need to expand ${procnm} in the here-doc; I just need to avoid the same happening to select *.

j4nd3r53n
  • 680
  • 2
  • 11
  • 26
  • Does this answer your question? [Block Comments in a Shell Script](https://stackoverflow.com/questions/947897/block-comments-in-a-shell-script) – ceving Jun 09 '20 at 12:27
  • Use single quotes around your end-of-input marker. https://unix.stackexchange.com/questions/68419/how-to-print-in-here-document – ceving Jun 09 '20 at 12:29
  • 2
    And stop writing security holes. Never build SQL statements by concatenation! Use prepared statements instead. – ceving Jun 09 '20 at 12:31
  • 1
    `$(echo $(cat $infile))` is a useless use of echo. And note that it is substituted by the string _verbatim_, it doesn't get executed. `when the select contains *` There is no "select" variable in your script. What contains `*`? How to reproduce your issue? Maybe instead of asking XY questions - what is that you really are trying to do? Do you want to output the content of the file `infille` before `end//`? And you do not export shell options, `set -o noglob` is only for current shell. – KamilCuk Jun 09 '20 at 12:51
  • @ceving What is it to you whether I build my statements up like this? I have considered the security implications, and in this case I have decided the risk is minimal. – j4nd3r53n Jun 09 '20 at 13:02
  • @KamilCuk I know all that - and I disagree that is a useless construction. `cat` will put the several lines of the file into a a string with line endings; `echo` then joins the lines up as one string. I find it usefule. – j4nd3r53n Jun 09 '20 at 13:05
  • Pufff, still `paste -sd' ' file` would be the way to join lines with a space. You are totally right, nonetheless. – KamilCuk Jun 09 '20 at 13:12
  • You do not need to expand `${procnm}`, because doing so would be a security hole. Just do it the right way. https://forums.mysql.com/read.php?20,160002,228438#msg-228438 – ceving Jun 09 '20 at 13:14

1 Answers1

0

I suspect it is because the construct echo (cat). The echo command gets the * from the cat command and the shell in which it runs expands it. In that shell set noglob is not active.

Try leaving the echo away: /$(cat $infile)/, in the end that is the data you need; then there is no extra glob expansion by a shell.

ruud
  • 743
  • 13
  • 22