Run an arbitrary SQL query from the specified file and return the
    the number of affected rows.

    .. versionadded:: 2017.7.0

    database

        database to run script inside

    file_name

        File name of the script.  This can be on the minion, or a file that is reachable by the fileserver

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.file_query mydb file_name=/tmp/sqlfile.sql
        salt '*' mysql.file_query mydb file_name=salt://sqlfile.sql

    Return data:

    .. code-block:: python

        {'query time': {'human': '39.0ms', 'raw': '0.03899'}, 'rows affected': 1L}

def file_query(database, file_name, **connection_args):
    '''
    Run an arbitrary SQL query from the specified file and return the
    the number of affected rows.

    .. versionadded:: 2017.7.0

    database

        database to run script inside

    file_name

        File name of the script.  This can be on the minion, or a file that is reachable by the fileserver

    CLI Example:

    .. code-block:: bash

        salt '*' mysql.file_query mydb file_name=/tmp/sqlfile.sql
        salt '*' mysql.file_query mydb file_name=salt://sqlfile.sql

    Return data:

    .. code-block:: python

        {'query time': {'human': '39.0ms', 'raw': '0.03899'}, 'rows affected': 1L}

    '''
    if any(file_name.startswith(proto) for proto in ('salt://', 'http://', 'https://', 'swift://', 's3://')):
        file_name = __salt__['cp.cache_file'](file_name)

    if os.path.exists(file_name):
        with salt.utils.files.fopen(file_name, 'r') as ifile:
            contents = salt.utils.stringutils.to_unicode(ifile.read())
    else:
        log.error('File "%s" does not exist', file_name)
        return False

    query_string = ""
    ret = {'rows returned': 0, 'columns': [], 'results': [], 'rows affected': 0, 'query time': {'raw': 0}}
    for line in contents.splitlines():
        if re.match(r'--', line):  # ignore sql comments
            continue
        if not re.search(r'[^-;]+;', line):  # keep appending lines that don't end in ;
            query_string = query_string + line
        else:
            query_string = query_string + line  # append lines that end with ; and run query
            query_result = query(database, query_string, **connection_args)
            query_string = ""

            if query_result is False:
                # Fail out on error
                return False

            if 'query time' in query_result:
                ret['query time']['raw'] += float(query_result['query time']['raw'])
            if 'rows returned' in query_result:
                ret['rows returned'] += query_result['rows returned']
            if 'columns' in query_result:
                ret['columns'].append(query_result['columns'])
            if 'results' in query_result:
                ret['results'].append(query_result['results'])
            if 'rows affected' in query_result:
                ret['rows affected'] += query_result['rows affected']
    ret['query time']['human'] = six.text_type(round(float(ret['query time']['raw']), 2)) + 's'
    ret['query time']['raw'] = round(float(ret['query time']['raw']), 5)

    # Remove empty keys in ret
    ret = {k: v for k, v in six.iteritems(ret) if v}

    return ret