#compdef mysql mysqlshow mysqldump mysqladmin
#
# zsh completion functions for mysql client programs
# Adam Spiers <adam@spiers.net>
#

##
## Auxiliary functions
##

_mysql_get_identity () {
  _mysql_user=${opt_args[-u]-$opt_args[--user]}
  _mysql_port=${opt_args[-P]-$opt_args[--port]}
  _mysql_host=${opt_args[-h]-$opt_args[--host]}

  _mysql_params=(
                 ${_mysql_user:+"--user=$_mysql_user"}
                 ${_mysql_host:+"--host=$_mysql_host"}
                 ${_mysql_port:+"--port=$_mysql_port"}
                )
}

_mysql_hosts () {
  local _mysql_user _mysql_port _mysql_host _mysql_params
  _mysql_get_identity

  _wanted hosts expl 'server host' \
    _combination -s '[:@]' '' hosts-ports-users \
      ${_mysql_user:+users=${_mysql_user:q}} \
      ${_mysql_port:+ports=${_mysql_port:q}} \
      hosts -
}

_mysql_ports () {
  local _mysql_user _mysql_port _mysql_host _mysql_params
  _mysql_get_identity

  _wanted ports expl 'server port' \
    _combination -s '[:@]' '' hosts-ports-users \
      ${_mysql_user:+users=${_mysql_user:q}} \
      ${_mysql_host:+hosts=${_mysql_host:q}} \
      ports -
}

_mysql_users () {
  local _mysql_user _mysql_port _mysql_host _mysql_params
  _mysql_get_identity

  _wanted users expl 'server username' \
    _combination -s '[:@]' '' hosts-ports-users \
      ${_mysql_host:+hosts=${_mysql_host:q}} \
      ${_mysql_port:+ports=${_mysql_port:q}} \
      users -
}

_mysql_databases () {
  local _mysql_user _mysql_port _mysql_host _mysql_params
  _mysql_get_identity

  local _mysql_databases
  _mysql_databases=(
                    ${(f)~~"$( echo "show databases" |
                               mysql "$_mysql_params[@]" )"}
                   )
  shift _mysql_databases

  compadd "$expl[@]" -a _mysql_databases
}

_mysql_tables () {
  local _mysql_user _mysql_port _mysql_host _mysql_params
  _mysql_get_identity

  local _mysql_tables
  _mysql_tables=(
                 ${(f)~~"$( echo "show tables" |
                              mysql "$_mysql_params[@]" $1 )"}
                )
  # remove header
  shift _mysql_tables

  compadd "$expl[@]" -a _mysql_tables
}

_mysql_variables () {
  _values -s , 'MySQL client variables' \
    'max_allowed_packet[maximum allowed packet size]:Packet size in bytes:' \
    'net_buffer_length[network buffer length]:Buffer length in bytes:'
}


##
## The actual completion code for the commands
##

_mysql_common_opts=(
    {-\?,--help}'[display help]'
    {-S+,--socket=}':server socket file:_files'
    {-h+,--host=}':server hostname:_mysql_hosts'
    {-P+,--port=}':server port:_mysql_ports'
    {-u+,--user=}':server username:_mysql_users'
    {-p+,--password=}':server password: '
    {-C,--compress}'[use compression in server/client protocol]'
)

_mysql () {
  local curcontext="$curcontext" state line expl
  typeset -A opt_args

  _arguments -C -s \
    "$_mysql_common_opts[@]" \
    {-V,--version}'[display client version]' \
    {-A,--no-auto-rehash}'[no automatic rehashing]' \
    '(-t --table)'{-B,--batch}'[batch mode (no pretty ASCII)]' \
    {-T,--debug-info}'[print debug info on exit]' \
    {-e,--exec-command}':batch-execute specified command and exit: ' \
    {-f,--force}'[continue through errors]' \
    {-i,--ignore-space}'[ignore space after function names]' \
    {-H,--html}'[produce HTML output]' \
    {-n,--unbuffered}'[flush the buffer after each query]' \
    {-O,--set-variable=}':set variable:_mysql_variables' \
    {-o,--one-database}'[only update the default database]' \
    {-q,--quick}'[disable caching of the result]' \
    {-r,--raw}'[write fields without conversion]' \
    {-s,--silent}'[silent mode]' \
    {-L,--skip-line-numbers}"[don't write line number for errors]" \
    {-N,--skip-column-names}"[don't write column names in results]" \
    '(-B --batch)'{-t,--table}'[output in table format]' \
    {-v,--verbose}'[verbose mode]' \
    {-E,--vertical}'[print query output vertically]' \
    {-w,--wait}'[wait and retry server connection if necessary]' \
    ':MySQL database to use:_mysql_databases'
}

_mysqlshow () {
  local curcontext="$curcontext" state line expl
  typeset -A opt_args

  _arguments -C -s \
    "$_mysql_common_opts[@]" \
    {-V,--version}'[display version]' \
    {-\#+,--debug=}':debug file: ' \
    ':MySQL database to show:_mysql_databases' \
    ':table to show:{ _mysql_tables "$line[1]" }' \
    ':field wildcard: '
}

_mysqldump () {
  local curcontext="$curcontext" state line expl
  typeset -A opt_args

  _arguments -C -s \
    "$_mysql_common_opts[@]" \
    {-V,--version}'[display version]' \
    {-a,--all}'[include all create options]' \
    {-\#+,--debug=}':debug file: ' \
    {-c,--complete-insert}'[use complete insert statements]' \
    {-e,--extended-insert}'[allow new INSERT syntax]' \
    "--add-drop-table[add a 'drop table' before each create]" \
    "--add-locks[add locks around insert statements]" \
    "--allow-keywords[allow creation of column names that are keywords]" \
    "--delayed[insert rows with INSERT DELAYED]" \
    {-F,--flush-logs}'[flush logs file in server before dump]' \
    {-l,--lock-tables}'[lock all tables for read]' \
    {-t,--no-create-info}"[don't write table creation info]" \
    {-d,--no-data}"[don't write row information]" \
    {-O,--set-variable}':set variable:_mysql_variables' \
    '--opt[create fastest possible dump for reading]' \
    {-q,--quick}"[don't buffer, dump directly to stdout]" \
    {-T,--tab=}"[dump tab-separated text files for each table]:directory to store text files:_files -/" \
    {-w+,--where=}'[dump only selected records]:WHERE clause to limit records to dump: ' \
    '--fields-terminated-by=:(with --tab) fields in textfile terminated by ...: ' \
    '--fields-enclosed-by=:(with --tab) fields in import file enclosed by ...: ' \
    '--fields-optionally-enclosed-by=:(with --tab) fields in import file optionally enclosed by ...: ' \
    '--fields-escaped-by=:(with --tab) fields in import file escaped by ...: ' \
    '--lines-terminated-by=:(with --tab) lines in import file terminated by ...: ' \
    ':MySQL database to dump:_mysql_databases' \
    '*:tables to dump:{ _mysql_tables "$line[1]" }'
}

_mysqladmin () {
  local curcontext="$curcontext" state line expl
  typeset -A opt_args

  _arguments -C -s \
    "$_mysql_common_opts[@]" \
    {-v,--version}'[display version]' \
    {-\#+,--debug=}':debug file: ' \
    {-f,--force}'[continue through errors]' \
    {-i+,--sleep=}'[repeat commands periodically]:number of seconds between executions: ' \
    {-s,--silent}"[silently exit if can't connect to server]" \
    {-t+,--timeout=}'[timeout for connection]' \
    {-w+,--wait=}'[wait and retry server connection if necessary]:number of retries: ' \
    '*::admin command:_mysqladmin_commands'
}

_mysqladmin_commands () {
  local cmds expl
  cmds=(
        create drop extended-status
        flush-{hosts,logs,status,tables,privileges}
        kill password ping processlist
        reload refresh shutdown
        status variables version
       )

  if (( CURRENT == 1 )); then
    _wanted commands expl command compadd "$@" -a cmds
  else
    local curcontext="$curcontext"

    case "${words[1]:t}" in
      (create|drop)
        _wanted mysqldbs expl "MySQL databases" _mysql_databases
      ;;
      (kill)
        _message -e ids 'thread ids'
      ;;
      (password)
        _message -e passwords 'new password'
      ;;
    esac
  fi
}

_mysql_utils () {
  case "$service" in
    mysql)
      _mysql "$@"
    ;;
    mysqlshow)
      _mysqlshow "$@"
    ;;
    mysqldump)
      _mysqldump "$@"
    ;;
    mysqladmin)
      _mysqladmin "$@"
    ;;
  esac
}

_mysql_utils "$@"
