예제 #1
0
/*
 * desc_disk_to_attr_info - convert RECDES for specified oid to 
 * HEAP_CACHE_ATTRINFO structure
 *    return: error status
 *    oid(in): the oid of the object
 *    recdes(in): RECDES structure to convert
 *    attr_info(out): the HEAP_CACHE_ATTRINFO structure
 */
static int
desc_disk_to_attr_info (THREAD_ENTRY * thread_p, OID * oid, RECDES * recdes,
			HEAP_CACHE_ATTRINFO * attr_info)
{
  if (oid == NULL || recdes == NULL || attr_info == NULL)
    {
      return ER_FAILED;
    }

  if (heap_attrinfo_clear_dbvalues (attr_info) != NO_ERROR)
    {
      return ER_FAILED;
    }

  if (heap_attrinfo_read_dbvalues (thread_p, oid, recdes, attr_info) !=
      NO_ERROR)
    {
      return ER_FAILED;
    }

  return NO_ERROR;
}
예제 #2
0
/*
 * xstats_update_class_statistics () -  Updates the statistics for the objects
 *                                    of a given class
 *   return:
 *   class_id(in): Identifier of the class
 *
 * Note: It first retrieves the whole catalog information about this class,
 *       including all possible forms of disk representations for the instance
 *       objects. Then, it performs a complete pass on the heap file of the
 *       class, reading in all of the instance objects one by one and
 *       calculating the ranges of numeric attribute values (ie. min. & max.
 *       values for each numeric attribute).
 *
 *       During this pass on the heap file, these values are maintained
 *       separately for objects with the same representation. Each minimum and
 *       maximum value is initialized when the first instance of the class
 *       with the corresponding representation is encountered. These values are
 *       continually updated as attribute values exceeding the known range are
 *       encountered. At the end of this pass, these individual ranges for
 *       each representation are uniformed in the last (the current)
 *       representation, building the global range values for the attributes
 *       of the class. Then, the btree statistical information is obtained for
 *       each attribute that is indexed and stored in this final representation
 *       structure. Finally, a new timestamp is obtained for these class
 *       statistics and they are stored to disk within the catalog structure
 *       for the last class representation.
 */
int
xstats_update_class_statistics (THREAD_ENTRY * thread_p, OID * class_id_p)
{
  CLS_INFO *cls_info_p = NULL;
  REPR_ID repr_id;
  DISK_REPR *disk_repr_p = NULL;
  DISK_ATTR *disk_attr_p = NULL;
  BTREE_STATS *btree_stats_p = NULL;
  HEAP_SCANCACHE hf_scan_cache, *hf_scan_cache_p = NULL;
  HEAP_CACHE_ATTRINFO hf_cache_attr_info, *hf_cache_attr_info_p = NULL;
  RECDES recdes;
  OID oid;
  SCAN_CODE scan_rc;
  DB_VALUE *db_value_p;
  DB_DATA *db_data_p;
  int i, j;

  cls_info_p = catalog_get_class_info (thread_p, class_id_p);
  if (cls_info_p == NULL)
    {
      goto error;
    }

  /* if class information was not obtained */
  if (cls_info_p->hfid.vfid.fileid < 0 || cls_info_p->hfid.vfid.volid < 0)
    {
      /* The class does not have a heap file (i.e. it has no instances);
         so no statistics can be obtained for this class; just set
         'tot_objects' field to 0 and return. */

      cls_info_p->tot_objects = 0;

      if (catalog_add_class_info (thread_p, class_id_p, cls_info_p) !=
	  NO_ERROR)
	{
	  goto error;
	}

      catalog_free_class_info (cls_info_p);
      return NO_ERROR;
    }

  if (catalog_get_last_representation_id (thread_p, class_id_p, &repr_id) !=
      NO_ERROR)
    {
      goto error;
    }

  disk_repr_p = catalog_get_representation (thread_p, class_id_p, repr_id);
  if (disk_repr_p == NULL)
    {
      goto error;
    }

  cls_info_p->tot_pages = file_get_numpages (thread_p,
					     &cls_info_p->hfid.vfid);
  cls_info_p->tot_objects = 0;
  disk_repr_p->num_objects = 0;

  /* scan whole object of the class and update the statistics */

  if (heap_scancache_start (thread_p, &hf_scan_cache, &(cls_info_p->hfid),
			    class_id_p, true, false,
			    LOCKHINT_NONE) != NO_ERROR)
    {
      goto error;
    }

  hf_scan_cache_p = &hf_scan_cache;

  if (heap_attrinfo_start (thread_p, class_id_p, -1, NULL,
			   &hf_cache_attr_info) != NO_ERROR)
    {
      goto error;
    }
  hf_cache_attr_info_p = &hf_cache_attr_info;

  /* Obtain minimum and maximum value of the instances for each attribute of
     the class and count the number of objects by scanning heap file */

  recdes.area_size = -1;
  scan_rc = heap_first (thread_p, &(cls_info_p->hfid), class_id_p, &oid,
			&recdes, hf_scan_cache_p, PEEK);

  while (scan_rc == S_SUCCESS)
    {
      if (heap_attrinfo_read_dbvalues (thread_p, &oid, &recdes,
				       hf_cache_attr_info_p) != NO_ERROR)
	{
	  scan_rc = S_ERROR;
	  break;
	}

      /* Consider attributes only whose type are fixed because min/max value
         statistics are useful only for those type when calculating the cost
         of query plan by query optimizer. Variable type attributes, for
         example VARCHAR(STRING), take constant number of selectivity. */

      for (i = 0; i < disk_repr_p->n_fixed; i++)
	{
	  disk_attr_p = &(disk_repr_p->fixed[i]);

	  db_value_p = heap_attrinfo_access (disk_attr_p->id,
					     hf_cache_attr_info_p);
	  if (db_value_p != NULL && db_value_is_null (db_value_p) != true)
	    {
	      db_data_p = db_value_get_db_data (db_value_p);

	      if (disk_repr_p->num_objects == 0)
		{
		  /* first object */
		  disk_attr_p->min_value = *db_data_p;
		  disk_attr_p->max_value = *db_data_p;
		}
	      else
		{
		  /* compare with previous values */
		  if (stats_compare_data (db_data_p, &disk_attr_p->min_value,
					  disk_attr_p->type) < 0)
		    {
		      disk_attr_p->min_value = *db_data_p;
		    }

		  if (stats_compare_data (db_data_p, &disk_attr_p->max_value,
					  disk_attr_p->type) > 0)
		    {
		      disk_attr_p->max_value = *db_data_p;
		    }
		}
	    }
	}

      cls_info_p->tot_objects++;
      disk_repr_p->num_objects++;

      scan_rc = heap_next (thread_p, &(cls_info_p->hfid), class_id_p, &oid,
			   &recdes, hf_scan_cache_p, PEEK);
    }

  if (scan_rc == S_ERROR)
    {
      goto error;
    }

  heap_attrinfo_end (thread_p, hf_cache_attr_info_p);
  if (heap_scancache_end (thread_p, hf_scan_cache_p) != NO_ERROR)
    {
      goto error;
    }

  /* update the index statistics for each attribute */

  for (i = 0; i < disk_repr_p->n_fixed + disk_repr_p->n_variable; i++)
    {
      if (i < disk_repr_p->n_fixed)
	{
	  disk_attr_p = disk_repr_p->fixed + i;
	}
      else
	{
	  disk_attr_p = disk_repr_p->variable + (i - disk_repr_p->n_fixed);
	}

      for (j = 0, btree_stats_p = disk_attr_p->bt_stats;
	   j < disk_attr_p->n_btstats; j++, btree_stats_p++)
	{
	  if (btree_get_stats (thread_p, &btree_stats_p->btid, btree_stats_p,
			       true) != NO_ERROR)
	    {
	      goto error;
	    }
	}
    }

  /* replace the current disk representation structure/information in the
     catalog with the newly computed statistics */

  if (catalog_add_representation (thread_p, class_id_p, repr_id, disk_repr_p)
      != NO_ERROR)
    {
      goto error;
    }

  cls_info_p->time_stamp = stats_get_time_stamp ();

  if (catalog_add_class_info (thread_p, class_id_p, cls_info_p) != NO_ERROR)
    {
      goto error;
    }

  if (disk_repr_p)
    {
      catalog_free_representation (disk_repr_p);
    }

  if (cls_info_p)
    {
      catalog_free_class_info (cls_info_p);
    }

  return NO_ERROR;

error:
  if (hf_cache_attr_info_p)
    {
      heap_attrinfo_end (thread_p, hf_cache_attr_info_p);
    }

  if (hf_scan_cache_p)
    {
      (void) heap_scancache_end (thread_p, hf_scan_cache_p);
    }

  if (disk_repr_p)
    {
      catalog_free_representation (disk_repr_p);
    }

  if (cls_info_p)
    {
      catalog_free_class_info (cls_info_p);
    }

  return er_errid ();
}