code: def _GetAttributeContainers(
        self, container_type, filter_expression=None, order_by=None):
      
      query = 'SELECT _identifier, _data FROM {0:s}'.format(container_type)
      if filter_expression:
        query = '{0:s} WHERE {1:s}'.format(query, filter_expression)
      if order_by:
        query = '{0:s} ORDER BY {1:s}'.format(query, order_by)
  
      # Use a local cursor to prevent another query interrupting the generator.
      cursor = self._connection.cursor()
  
      try:
        cursor.execute(query)
      except sqlite3.OperationalError as exception:
        raise IOError('Unable to query storage file with error: {0!s}'.format(
            exception))
  
      row = cursor.fetchone()
      while row:
        identifier = identifiers.SQLTableIdentifier(container_type, row[0])
  
        if self.compression_format == definitions.COMPRESSION_FORMAT_ZLIB:
          serialized_data = zlib.decompress(row[1])
        else:
          serialized_data = row[1]
  
        if self._storage_profiler:
          self._storage_profiler.Sample(
              'read', container_type, len(serialized_data), len(row[1]))
  
        attribute_container = self._DeserializeAttributeContainer(
            container_type, serialized_data)
        attribute_container.SetIdentifier(identifier)
        yield attribute_container
  
        row = cursor.fetchone()
docs: Retrieves a specific type of stored attribute containers.
  
      Args:
        container_type (str): attribute container type.
        filter_expression (Optional[str]): expression to filter results by.
        order_by (Optional[str]): name of a column to order the results by.
  
      Yields:
        AttributeContainer: attribute container.
  
      Raises:
        IOError: when there is an error querying the storage file.
        OSError: when there is an error querying the storage file.