/* * 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; }
/* * 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 (); }