#!/bin/sh # use /bin/sh or /bin/ksh # # shql - version 1.1 # # DEFINE THESE setglobal SHQL_ROOT = '"/u/shql'" # system-wide database location setglobal EDITOR = $(EDITOR:=/usr/bin/vi) # default editor if EDITOR not defined setglobal SHELL = $(SHELL:=/bin/sh) # default shell if SHELL not defined setglobal AWK = 'mawk' # Unix table file postfixes: @ is attrib, ~ is data, % is view setglobal DEBUG = '"N'" # set to Y for debugging test $DEBUG = "Y" && set -x # uncomment for debugging #set -v setglobal UMASK = $[umask] umask 0000 # share database trap "echo \"Goodbye\" ; \ rm -f /tmp/$Pid /tmp/$Pidrow /tmp/$Pidjoin*" 0 1 2 3 15 set -h # remember functions if echo '\c' | grep -s c { # to adapt to System V vs. BSD 'echo' setglobal NOCR1 = ''-n'' # BSD setglobal NOCR2 = ''"" } else { setglobal NOCR1 = ''"" # System V setglobal NOCR2 = ''\c'' } setglobal NL = '' '' setglobal TAB = '' '' export _IFS TABLE CMD NOCR1 NOCR2 NL TAB setglobal _IFS = $IFS if test "X$1" = "X-q" { setglobal QUIET = '"Y'" shift } if test "X$1" = "X" { echo "Missing database name." !1 > !2 echo "The database name must be a directory under $HOME/shql" !1 > !2 echo " or a directory under $SHQL_ROOT" !1 > !2 exit 1 } echo "Database: $1" if test -d $HOME/shql/$1 { cd $HOME/shql/$1 } elif test -d $SHQL_ROOT/$1 { cd $SHQL_ROOT/$1 } elif test -d $HOME/$1 { cd $HOME/$1 } elif test -d $1 { cd $1 } else { echo "Unknown database ($1)" !1 > !2 echo "The database name must be a directory under $HOME/shql" !1 > !2 echo " or a directory under $SHQL_ROOT" !1 > !2 exit 1 } # #************************************************************************** # syntax #************************************************************************** proc syntax{ match $1 { with create cat << ''' CREATE TABLE table_name ( column_name column_width {, ...} ) or CREATE VIEW view_name ( table_or_view1.column1 = table_or_view2.column2 ) ''' return 0 with delete cat << ''' DELETE FROM table_name { WHERE where_clause } ''' return 0 with drop cat << ''' DROP TABLE table_name or DROP VIEW view_name ''' return 0 with edit cat << ''' EDIT table_name is a non-standard method of changing a table's field names or display widths. ''' return 0 with help cat << ''' HELP ALL or HELP TABLES or HELP VIEWS or HELP COMMANDS or HELP [CREATE | DELETE | DROP | INSERT | SELECT | UPDATE | WHERE | PRINT | EDIT] or HELP table_name Commands must appear in lower case. ''' return 0 with insert cat << ''' INSERT INTO table_name { ( column_name, ... ) } VALUES ( expression, ...) or INSERT INTO table_name { ( column_name, ... ) } subselect ''' return 0 with print cat << ''' PRINT table_name is a non-standard synonym for SELECT * FROM table_name. ''' return 0 with select cat << ''' SELECT { DISTINCT } [ column_name {,...} | * ] FROM [ table_name | view_name ] { WHERE where_clause } { ORDER BY column_name { NUM } { ASC | DESC } {, ... } { UNION select statement } 'NUM' is a non-standard method for sorting numeric fields. ''' return 0 with update cat << ''' UPDATE table_name SET column_name = expression {, ... } { WHERE where_clause } ''' return 0 with where cat << ''' WHERE [ column_name | value ] [ =, !=, >, <, >=, <=, and, or, not, in ] [ column_name | value | subselect ] Parentheses may be used to group expressions. ''' return 0 with syntax syntax commands; echo syntax create; echo syntax delete; echo syntax drop; echo syntax insert; echo syntax select; echo syntax update; echo syntax where; echo syntax print; echo syntax edit; echo return 0 } return 1 } # #************************************************************************** # lookup_field #************************************************************************** proc lookup_field{ if test ! -f $TABLE% { setglobal RESULT = $[grep -n '"'^$1 '"' $TABLE@] } else { setglobal RESULT = $[grep -n '"'^$1 '"' $TABLE@ | sed 1q] } if test ! $RESULT { setglobal OUTFIELD = $1 return 1 } else { setglobal OUTFIELDNUM = $[expr $RESULT : '\([^:]*\)] setglobal OUTFIELD = ""\$$OUTFIELDNUM"" return 0 } } # #************************************************************************** # do_aggreg #************************************************************************** proc do_aggreg{ if test "X$1" = 'Xsum' { setglobal AGGREG = ''total'' } elif test "X$1" = 'Xavg' { setglobal AGGREG = ''(total/cnt)'' } elif test "X$1" = 'Xcount' { setglobal AGGREG = ''cnt'' } elif test "X$1" = 'Xmin' { setglobal AGGREG = ''min'' } elif test "X$1" = 'Xmax' { setglobal AGGREG = ''max'' } else { return 1 } test "X$2" != "X(" -o "X$4" != "X)" && \ echo "Bad aggregate syntax" !1 > !2 && syntax select && return 1 setglobal AGGFIELD = $3 shift 4 lookup_field $AGGFIELD test "$Status" -ne 0 && echo "Bad field name ($1)" !1 > !2 && return 1 while [ $# -ne 0 ] { test "X$1" = "Xwhere" && break; test "X$1" = "Xorder" && break; test "X$1" = "Xunion" && break; shift } setglobal OUTFIELD = $[shell { setglobal SUBSELECT = '"Y'" ; setglobal AGGREGATE = '"Y'"; \ select_ "select" $AGGFIELD "from" $TABLE @Argv} | \ $AWK -F" " \ 'NR == 1 { min = $1; max = $1 } { cnt += 1; total += $1 } $1 < min { min = $1 } $1 > max { max = $1 } END { printf "%s%s%s", "\"", '$AGGREG', "\"" }] if test $[expr $RESULT : '[^ ]* \(.*\)] -lt 10 { setglobal RESULT = ""$AGGFIELD 10"" } return 0 } # #************************************************************************** # do_join #************************************************************************** proc do_join{ update_view $1 setglobal TABLE = $1 lookup_field $2 test "$Status" -ne 0 && echo "Bad view specifcation ($1.$2)" !1 > !2 && return 1 setglobal JFIELD1 = $OUTFIELDNUM setglobal JFIELD1L1 = $[expr $JFIELD1 - 1] update_view $3 setglobal TABLE = $3 lookup_field $4 test "$Status" -ne 0 && echo "Bad view specifcation ($3.$4)" !1 > !2 && return 1 setglobal JFIELD2 = $OUTFIELDNUM setglobal JFIELD2L1 = $[expr $JFIELD2 - 1] shell { grep "^$2 " $1@ ; grep -v "^$2 " $1@ ; grep -v "^$4 " $3@ } > $5@ sort -t' ' +$JFIELD2L1 $3~ > /tmp/$Pid sort -t' ' +$JFIELD1L1 $1~ | \ join -t' ' -j1 $JFIELD1 -j2 $JFIELD2 \ - /tmp/$Pid > $5~ } # #************************************************************************** # update_view #************************************************************************** proc update_view{ test ! -f "$1%" && return 1 shell { do_join $[cat $1%] } } # #************************************************************************** # where #************************************************************************** proc where{ shift while [ $# -gt 0 -a "$1" != "order" -a "$1" != "union" ] { if test "X$1" = "Xselect" { set X $[shell { setglobal SUBSELECT = '"Y'" ;select_ @Argv}] if test "$Status" -eq 0 { shift } else { return 1 } } match $1 { with and setglobal WHERE = ""$WHERE && "" with or setglobal WHERE = ""$WHERE || "" with not setglobal WHERE = ""$WHERE !"" with = setglobal WHERE = ""$WHERE == "" with 'in' shift set X $[shell { setglobal SUBSELECT = ''Y'';select_ @Argv }] if test "$Status" -eq 0 { shift } else { return 1 } setglobal INWHERE = ''"" setglobal COMP = '"=='" setglobal LOGIC = '"||'" test "X$LAST" = "Xnot" && setglobal COMP = '"='" && setglobal LOGIC = '"&&'for VALUE in @Argv { test "X$INWHERE" != "X" && setglobal INWHERE = ""$INWHERE $LOGIC"" setglobal INWHERE = ""$INWHERE ($WHERE$COMP $VALUE) "" } setglobal WHERE = $INWHERE break with * lookup_field $1 setglobal WHERE = ""$WHERE $OUTFIELD"" } setglobal LAST = $1 shift } test $WHERE && setglobal WHERE = "" ( $WHERE ) "" && return 0 echo "Missing 'where' clause" !1 > !2 syntax where return 1 } # #************************************************************************** # help #************************************************************************** proc help{ if test ! $2 { echo "Ambiguous syntax, try:" !1 > !2 ; syntax help } elif test $2 = "all" { ls *@ *% !2 >/dev/null | cut -d@ -f1 | cut -d% -f1 | uniq } elif test $2 = "tables" { ls *@ *% !2 >/dev/null | cut -d@ -f1 | cut -d% -f1 | uniq -u } elif test $2 = "views" { ls *% !2 >/dev/null | cut -d% -f1 } elif test $2 = "commands" { cat << ''' /p is print /g is go(execute) /q is quit /e is edit /i is include /w is write /r is reset(clear) /s is shell /p/g print and go The number sign(#) may be used at the start of a line for comments. ''' } else { syntax $2 && return setglobal TABLE = $2 update_view $TABLE if test -f "$2@" { echo "$NL <$2>" && cat "$2@" test -f "$(2)%" &&echo $NOCR1 "$NL View: $NOCR2" && set X $[cat $2%] && shift && echo "$1.$2 = $3.$4" echo "$NL Rows: "$[cat $TABLE~ | wc -l] } else { echo "$TABLE does not exist." !1 > !2 syntax help } } } # #************************************************************************** # create #************************************************************************** proc create{ shift if test -f "$2@" -o -f "$2%" { echo "Table already exists." !1 > !2 } elif test "X$1" = "Xview" -a $Argc -gt 2 { shift if test $Argc -ne 6 { syntax create } else { test "X$2" != "X(" && echo "Bad syntax" !1 > !2 && syntax create && return setglobal TABLE1 = $[expr $3 : '\([^\.]*\)] setglobal FIELD1 = $[expr $3 : '[^\.]*.\(.*\)] setglobal TABLE = $TABLE1 lookup_field $FIELD1 test "$Status" -ne 0 && echo "Bad table or field name" !1 > !2 && return test "X$4" != "X=" && echo "Bad syntax" !1 > !2 && syntax create && return setglobal TABLE2 = $[expr $5 : '\([^\.]*\)] setglobal FIELD2 = $[expr $5 : '[^\.]*.\(.*\)] setglobal TABLE = $TABLE2 lookup_field $FIELD2 test "$Status" -ne 0 && echo "Bad table or field name" !1 > !2 && return test "X$2" != "X(" && echo "Bad syntax" !1 > !2 && syntax create && return echo "$TABLE1 $FIELD1 $TABLE2 $FIELD2 $1" > $1% update_view $1 } echo "OK" } elif test "X$1" = "Xtable" -a $Argc -ge 5 { test "X$3" != "X(" && echo "Bad syntax" !1 > !2 && syntax create && return setglobal TABLE = $2 shift 3 > $TABLE@ > $TABLE~ while [ $# -ge 2 ] { echo "$1 $2" >> $TABLE@ shift 2 } test "X$1" != "X)" && echo "Bad syntax" !1 > !2 && rm -f $TABLE[@~] && syntax create && return echo "OK" } else { echo "Improper syntax ($1)" !1 > !2 syntax create } return } # #************************************************************************* # drop #************************************************************************** proc drop{ test $2 != "table" -a $2 != "view" && echo "Syntax error." !1 > !2 && syntax drop && return test $2 = "table" -a -f "$3%" && echo "Can not drop, $2 is a view, not a table" !1 > !2 && return test $2 = "view" -a ! -f "$3%" && echo "Can not drop, $2 is not a view" !1 > !2 && return if test -f "$3@" -o -f "$3%" { rm -f $3@ $3~ $3% echo "OK" } else { echo "No such table" !1 > !2 } } # #************************************************************************** # insert #************************************************************************** proc insert{ shift test "X$1" != "Xinto" && echo "Improper syntax ($1)" !1 > !2 && syntax insert && return shift setglobal TABLE = $1 update_view $TABLE && echo "Can not insert into a view" !1 > !2 && return test ! -f "$TABLE@" && echo "Table does not exist" !1 > !2 && return shift setglobal ATTRIB = $[cat $TABLE@ | wc -l] setglobal XASGN = ''"" setglobal XECHO = '"echo '\"" if test $Argc -gt 0 -a "X$1" = "X(" { setglobal ATTRIB2 = '"0'" shift while [ $# -gt 0 -a "X$1" != "X)" ] { lookup_field $1 test "$Status" -ne 0 && echo "Bad field name. ($1)" !1 > !2 && return setglobal XASGN = ""$XASGN X$OUTFIELDNUM=\`eval echo \$1\` ; shift;"" shift setglobal ATTRIB2 = $[expr $ATTRIB2 + 1] } test "X$1" != "X)" && echo "Syntax error ($1)" !1 > !2 && syntax insert && return shift setglobal POS = '"1'" while [ "$POS" -le "$ATTRIB" ] { eval X$POS="" test $POS != "1" && setglobal XECHO = ""$XECHO\$TAB"" setglobal XECHO = ""$XECHO\$X$POS"" setglobal POS = $[expr $POS + 1] } setglobal XECHO = ""$XECHO"\"" setglobal ATTRIB = $ATTRIB2 } if test "X$1" = "Xselect" { eval set X "$[shell { setglobal SUBSELECT = ''Y'' ; select_ @Argv }] \)" shift } elif test "X$1" != "Xvalues" -o "X$2" != 'X(' { echo "Improper syntax ($1)" !1 > !2 && syntax insert && return } else { shift 2 }for LAST in @Argv { : ; } test "X$LAST" != "X)" && echo "Improper syntax" !1 > !2 && syntax insert && return if test $[expr '(' $Argc - 1 ')' % $ATTRIB] -ne 0 { echo "Incorrect number of values." !1 > !2 } else { setglobal ROWS = $[expr '(' $Argc - 1 ')' / $ATTRIB] while [ $# -gt 1 ] { if test $XASGN = "" { echo $NOCR1 "$[eval echo $1]$NOCR2" >> $TABLE~ shift while [ "`expr \( $# - 1 \) % $ATTRIB`" -ne 0 ] { echo $NOCR1 "$TAB$[eval echo $1]$NOCR2"\ >> $TABLE~ shift } echo "" >> $TABLE~ } else { eval $XASGN eval $XECHO >> $TABLE~ } } echo "($ROWS rows)" } } # #************************************************************************* # delete #************************************************************************** proc delete{ shift setglobal TABLE = $2 update_view $TABLE && echo "You can not delete from a view." !1 > !2 && return test ! -f "$TABLE@" && echo "$TABLE does not exit." !1 > !2 && return setglobal WHERE = ''"" if test "X$3" = "Xwhere" { shift 2 where @Argv && $AWK -F" " "! $WHERE { cnt += 1 ; print } END { printf \"( %1d rows.)\\n\", (NR - cnt) \ >\"/tmp/$Pidrow\" }" $TABLE~ > /tmp/$Pid && mv /tmp/$Pid $TABLE~ && cat /tmp/$Pidrow } else { echo '('$[cat $TABLE~ | wc -l]' rows)' > $TABLE~ } } # #************************************************************************* # update #************************************************************************** proc update{ setglobal TABLE = $2 update_view $TABLE && echo "Can not update a view." !1 > !2 && return test ! -f "$TABLE@" && echo "$TABLE does not exit." !1 > !2 && return test "X$3" != "Xset" && echo "Improper syntax." !1 > !2 && syntax update && return shift 3 setglobal ASSIGN = ''"" while [ $# -gt 0 -a "X$1" != "Xwhere" ] { lookup_field $1 && test "X$2" = "X=" && setglobal ASSIGN = ""$ASSIGN ; "" setglobal ASSIGN = ""$ASSIGN $OUTFIELD"" shift } setglobal WHERE = ''"" if test "X$1" = "Xwhere" { where @Argv || return } $AWK -F" " "BEGIN { OFS = \" \" } $WHERE { $ASSIGN; cnt += 1 } { print } END { printf \"( %1d rows)\\n\", cnt >\"/tmp/$Pidrow\" }" \ $TABLE~ > /tmp/$Pid && mv /tmp/$Pid $TABLE~ && cat /tmp/$Pidrow } # #************************************************************************** # select_ #************************************************************************** proc select_{ test $DEBUG = "Y" && set -x # uncomment for debugging setglobal UNION = '"Y'" while [ "$UNION" != "" ] { setglobal INAGG = ''"" setglobal FROM = ''"" setglobal UNION = ''"" setglobal TABLE = ''for ATABLE in @Argv { test "X$ATABLE" = "Xwhere" && break test "X$ATABLE" = "Xorder" && break test "X$ATABLE" = "Xunion" && break test "X$ATABLE" = "Xfrom" && setglobal FROM = '"Y'" && continue if test $FROM { test ! -f "$ATABLE@" && \ echo "$ATABLE does not exist." !1 > !2 && return 1 if test ! $TABLE { setglobal TABLE = $ATABLE } else { setglobal JTABLE = $TABLE setglobal PREV = ''"" setglobal PPREV = ''"" setglobal FOUND = ''for GETJ in @Argv { if test $PREV = "=" { setglobal TABLE = $JTABLE lookup_field $PPREV && setglobal TABLE = $ATABLE && lookup_field $GETJ && setglobal FOUND = '"Y1'" && break setglobal TABLE = $ATABLE lookup_field $PPREV && setglobal TABLE = $JTABLE && lookup_field $GETJ && setglobal FOUND = '"Y2'" && break } setglobal PPREV = $PREV setglobal PREV = $GETJ } test ! $FOUND && echo "Join not found, \c" && echo "try reordering tables." !1 > !2 && return 1 if test $FOUND = "Y1" { echo "$JTABLE $PPREV $ATABLE $GETJ /tmp/$Pidjoin2" >/tmp/$Pidjoin2% } else { echo "$ATABLE $PPREV $JTABLE $GETJ /tmp/$Pidjoin2" >/tmp/$Pidjoin2% } update_view /tmp/$Pidjoin2 mv /tmp/$Pidjoin2~ /tmp/$Pidjoin~ mv /tmp/$Pidjoin2@ /tmp/$Pidjoin@ expr $RESULT : '[^:]:*\(.*\)' >>/tmp/$Pidjoin@ cut -d' ' -f1 /tmp/$Pidjoin~ | \ paste /tmp/$Pidjoin~ - >/tmp/$Pid mv /tmp/$Pid /tmp/$Pidjoin~ setglobal TABLE = ""/tmp/$Pidjoin"" } } } test ! $FROM && echo "Syntax error." !1 > !2 && syntax select && return 1 update_view $TABLE shift setglobal DISTINCT = ''"" test "X$1" = "Xdistinct" && setglobal DISTINCT = '"Y'" && shift setglobal FIELDS = ''"" setglobal PRINTF = ''"" while [ "X$1" != "Xfrom" ] { if test "X$1" = 'X*' { shift set X $[cat $TABLE@ | cut -d' ' -f1] @Argv shift } else { lookup_field $1 if test "$Status" -ne 0 { do_aggreg @Argv if test "$Status" -eq 0 { setglobal INAGG = '"Y'" shift 3 } else { echo "Bad field name ($1)" !1 > !2 return 1 } } test $FIELDS && setglobal FIELDS = ""$FIELDS,"" setglobal FIELDS = ""$FIELDS $OUTFIELD"" if test $SUBSELECT = "" { test ! $PRINTF && setglobal PRINTF = '"|'" setglobal WIDTH = $[expr $RESULT : \ '[^ ]* \(.*\)] setglobal PRINTF = ""$PRINTF%-$WIDTH.$(WIDTH)s|"" } else { if test ! $AGGREGATE { setglobal PRINTF = ""$PRINTF\\\"%s\\\" "" } else { setglobal PRINTF = ""$PRINTF%s\n"" } } shift } } shift 2 setglobal WHERE = ''"" setglobal SORT = ''"" while [ $# -ne 0 ] { if test "X$1" = "Xwhere" { where @Argv test "$Status" -ne 0 && return 1 setglobal WHERE = ""$WHERE || NR == 1"" shift } elif test "X$1" = "Xorder" { test "X$2" != "Xby" && echo "Syntax error ($2)" !1 > !2 && syntax select && return 1 shift 2 while [ $# -gt 0 -a "$1" != "union" ] { if test "X$1" != "Xasc" -a \ "X$1" != "Xdesc" -a \ "X$1" != "Xnum" { lookup_field $1 test "$Status" -ne 0 && echo "Bad field name ($1)" !1 > !2 && return 1 test $SORT = "" && setglobal SORT = '"sort -t\" \" '" setglobal SORTL = $[expr $OUTFIELDNUM - 1] setglobal SORT = ""$SORT +$SORTL"" test "X$2" = "Xnum" && setglobal SORT = ""$(SORT)n"" test "X$2" = "Xdesc" && setglobal SORT = ""$(SORT)r"" test "X$3" = "Xdesc" && setglobal SORT = ""$(SORT)r"" setglobal SORT = ""$SORT -$OUTFIELDNUM"" } shift } } elif test "X$1" = "Xunion" { shift setglobal UNION = '"Y'" break } else { shift } } test $INAGG && setglobal WHERE = '"NR == 1'" if test $DISTINCT != "" { if test $SORT = "" { setglobal DIST = ""sort | uniq | tee /tmp/$Pidrow"" } else { setglobal DIST = ""uniq | tee /tmp/$Pidrow"" } } else { setglobal DIST = '"cat'" } setglobal TABLEFILE = ""$TABLE~"" test $SORT != "" && cat $TABLE~ | eval $SORT > /tmp/$Pid && setglobal TABLEFILE = ""/tmp/$Pid"" if test $SUBSELECT { $AWK -F" " "$WHERE {printf \"$PRINTF\", $FIELDS }" \ $TABLEFILE |eval $DIST } else { if test ! $QUIET -o $INAGG = "Y" { shell { set X $[cut -d' ' -f1 $TABLE@] ; shift echo $NOCR1 "-$1-$NOCR2" ; shiftfor HEADING in @Argv { echo $NOCR1 "$TAB-$HEADING-$NOCR2" } ; echo "" } } | $AWK -F" " \ "$WHERE { cnt += 1 ; printf \"$PRINTF\\n\", $FIELDS } END { printf \"( %1d rows)\\n\", (cnt - 1) \ >\"/tmp/$Pidrow\" }" - $TABLEFILE | eval $DIST \ && if test $DISTINCT = "" { cat /tmp/$Pidrow } else { setglobal X = $[expr '`'cat /tmp/$Pidrow|wc -l'`' - 1] echo '('$X' rows)' } } } return 0 } # #************************************************************************** # main #************************************************************************** while : { while : { echo $NOCR1 "* $NOCR2" read LINE || exit setglobal SQLPART = $[expr $LINE : '\(..*\)/.$] if test $SQLPART != "" { test $NEW = "Y" && setglobal _CMD = ''"" if test $[expr $LINE : '.*/p/g$] -ne 0 { setglobal _CMD = ""$_CMD"$[expr $LINE : '\(.*\)/p/g$]"$NL"" setglobal LINE = '"/p/g'" setglobal NEW = ''"" } else { setglobal _CMD = ""$_CMD""$SQLPART""$NL"" setglobal LINE = $[expr $LINE : '.*\(/.\)$] setglobal NEW = ''"" } } match $LINE { with /p|p echo $_CMD with /g|g break with /p/g|pg echo $_CMD ; break with /r|r echo "reset" ; setglobal _CMD = ''"" with /s|s umask $UMASK ; $SHELL ; umask 0000 with /e|e umask $UMASK ; echo $_CMD > /tmp/$Pid $EDITOR /tmp/$Pid; setglobal _CMD = $[cat /tmp/$Pid] umask 0000 with /i|i echo $NOCR1 "Enter include file: $NOCR2" read LINE test -f $LINE && setglobal _CMD = ""$_CMD$[cat $LINE]$NL"" && echo "$LINE included" with /w|w echo $NOCR1 "Enter output file: $NOCR2" read LINE test $LINE && umask $UMASK && echo $_CMD > $LINE && umask 0000 && echo "$LINE written" with /q|q exit 0 with \#* test $NEW = "Y" && setglobal _CMD = ''"" with * test $NEW = "Y" && setglobal _CMD = ''"" setglobal _CMD = ""$_CMD$LINE$NL"" } setglobal NEW = ''"" } setglobal CMD = $[echo $_CMD | sed \ -e "s/\'/\"/g" \ -e 's/\"\([^\"]*\)\"/\"\\\"\1\\\"\"/g' \ -e 's/\([<>!=][<>!=]*\)/ \1 /g' \ -e 's//\\\>/g' \ -e 's/\*/\\\*/g' \ -e 's/(/ \\\( /g' \ -e 's/)/ \\\) /g] test ! $CMD && continue setglobal IFS = ""$_IFS,"" eval set X $CMD shift setglobal IFS = $_IFS setglobal NEW = '"Y'" match $1 { with select select_ @Argv with create create @Argv with delete delete @Argv with drop drop @Argv with insert insert @Argv with update update @Argv with edit test $2 && $EDITOR $2@ with help help @Argv with print select_ "select" '*' "from" $2 with * echo "Missing or unrecognized command." !1 > !2 } }