Checks to make sure the given row exists. If row exists and update is True
    then row will be updated with data. Otherwise it will leave existing
    row unmodified and check it against data. If the existing data
    doesn't match data_check the state will fail.  If the row doesn't
    exist then it will insert data into the table. If more than one
    row matches, then the state will fail.

    name
        Only used as the unique ID

    db
        The database file name

    table
        The table name to check the data

    data
        The dictionary of key/value pairs to check against if
        row exists, insert into the table if it doesn't

    where_sql
        The sql to select the row to check

    where_args
        The list parameters to substitute in where_sql

    update
        True will replace the existing row with data
        When False and the row exists and data does not equal
        the row data then the state will fail

def row_present(name,
                db,
                table,
                data,
                where_sql,
                where_args=None,
                update=False):
    '''
    Checks to make sure the given row exists. If row exists and update is True
    then row will be updated with data. Otherwise it will leave existing
    row unmodified and check it against data. If the existing data
    doesn't match data_check the state will fail.  If the row doesn't
    exist then it will insert data into the table. If more than one
    row matches, then the state will fail.

    name
        Only used as the unique ID

    db
        The database file name

    table
        The table name to check the data

    data
        The dictionary of key/value pairs to check against if
        row exists, insert into the table if it doesn't

    where_sql
        The sql to select the row to check

    where_args
        The list parameters to substitute in where_sql

    update
        True will replace the existing row with data
        When False and the row exists and data does not equal
        the row data then the state will fail
    '''
    changes = {'name': name,
               'changes': {},
               'result': None,
               'comment': ''}
    conn = None
    try:
        conn = sqlite3.connect(db, detect_types=sqlite3.PARSE_DECLTYPES)
        conn.row_factory = _dict_factory
        rows = None
        if where_args is None:
            rows = _query(conn, "SELECT * FROM `" +
                                table + "` WHERE " + where_sql)
        else:
            rows = _query(conn, "SELECT * FROM `" +
                                table + "` WHERE " + where_sql,
                                where_args)

        if len(rows) > 1:
            changes['result'] = False
            changes['comment'] = 'More than one row matched the specified query'
        elif len(rows) == 1:
            for key, value in six.iteritems(data):
                if key in rows[0] and rows[0][key] != value:
                    if update:
                        if __opts__['test']:
                            changes['result'] = True
                            changes['comment'] = "Row will be update in " + table

                        else:
                            columns = []
                            params = []
                            for key, value in six.iteritems(data):
                                columns.append("`" + key + "`=?")
                                params.append(value)

                            if where_args is not None:
                                params += where_args

                            sql = "UPDATE `" + table + "` SET "
                            sql += ",".join(columns)
                            sql += " WHERE "
                            sql += where_sql
                            cursor = conn.execute(sql, params)
                            conn.commit()
                            if cursor.rowcount == 1:
                                changes['result'] = True
                                changes['comment'] = "Row updated"
                                changes['changes']['old'] = rows[0]
                                changes['changes']['new'] = data
                            else:
                                changes['result'] = False
                                changes['comment'] = "Row update failed"
                    else:
                        changes['result'] = False
                        changes['comment'] = "Existing data does" + \
                                             "not match desired state"
                        break

            if changes['result'] is None:
                changes['result'] = True
                changes['comment'] = "Row exists"
        else:
            if __opts__['test']:
                changes['result'] = True
                changes['changes']['new'] = data
                changes['comment'] = "Row will be inserted into " + table
            else:
                columns = []
                value_stmt = []
                values = []
                for key, value in six.iteritems(data):
                    value_stmt.append('?')
                    values.append(value)
                    columns.append("`" + key + "`")

                sql = "INSERT INTO `" + table + "` ("
                sql += ",".join(columns)
                sql += ") VALUES ("
                sql += ",".join(value_stmt)
                sql += ")"
                cursor = conn.execute(sql, values)
                conn.commit()
                if cursor.rowcount == 1:
                    changes['result'] = True
                    changes['changes']['new'] = data
                    changes['comment'] = 'Inserted row'
                else:
                    changes['result'] = False
                    changes['comment'] = "Unable to insert data"

    except Exception as e:
        changes['result'] = False
        changes['comment'] = six.text_type(e)

    finally:
        if conn:
            conn.close()

    return changes