docs: 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