CUBRID Engine  latest
statistics_sr.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * statistics_sr.c - statistics manager (server)
21  */
22 
23 #ident "$Id$"
24 
25 #include "config.h"
26 
27 #include <stdio.h>
28 #include <string.h>
29 #include <math.h>
30 
31 #include "statistics_sr.h"
32 
33 #include "btree.h"
34 #include "heap_file.h"
35 #include "boot_sr.h"
36 #include "partition_sr.h"
37 #include "object_primitive.h"
38 #include "object_representation.h"
39 #include "thread_entry.hpp"
40 #include "system_parameter.h"
41 
42 #define SQUARE(n) ((n)*(n))
43 
44 /* Used by the "stats_update_all_statistics" routine to create the list of all
45  classes from the extensible hashing directory used by the catalog manager. */
48 {
51 };
52 
55 {
56  double leafs; /* number of leaf pages including overflow pages */
57  double pages; /* number of total pages */
58  double height; /* the height of the B+tree */
59  double keys; /* number of keys */
60  int pkeys_size; /* pkeys array size */
61  double *pkeys; /* partial keys info for example: index (a, b, ..., x) pkeys[0] -> # of {a} pkeys[1] ->
62  * # of {a, b} ... pkeys[pkeys_size-1] -> # of {a, b, ..., x} */
63 };
64 
65 #if defined(ENABLE_UNUSED_FUNCTION)
66 static int stats_compare_data (DB_DATA * data1, DB_DATA * data2, DB_TYPE type);
67 static int stats_compare_date (DB_DATE * date1, DB_DATE * date2);
68 static int stats_compare_time (DB_TIME * time1, DB_TIME * time2);
69 static int stats_compare_utime (DB_UTIME * utime1, DB_UTIME * utime2);
70 static int stats_compare_datetime (DB_DATETIME * datetime1_p, DB_DATETIME * datetime2_p);
71 static int stats_compare_money (DB_MONETARY * mn1, DB_MONETARY * mn2);
72 #endif
73 static int stats_update_partitioned_statistics (THREAD_ENTRY * thread_p, OID * class_oid, OID * partitions, int count,
74  bool with_fullscan);
75 
76 /*
77  * xstats_update_statistics () - Updates the statistics for the objects
78  * of a given class
79  * return:
80  * class_id(in): Identifier of the class
81  * with_fullscan(in): true iff WITH FULLSCAN
82  *
83  * Note: It first retrieves the whole catalog information about this class,
84  * including all possible forms of disk representations for the instance
85  * objects. Then, it performs a complete pass on the heap file of the
86  * class, reading in all of the instance objects one by one and
87  * calculating the ranges of numeric attribute values (ie. min. & max.
88  * values for each numeric attribute).
89  *
90  * During this pass on the heap file, these values are maintained
91  * separately for objects with the same representation. Each minimum and
92  * maximum value is initialized when the first instance of the class
93  * with the corresponding representation is encountered. These values are
94  * continually updated as attribute values exceeding the known range are
95  * encountered. At the end of this pass, these individual ranges for
96  * each representation are uniformed in the last (the current)
97  * representation, building the global range values for the attributes
98  * of the class. Then, the btree statistical information is obtained for
99  * each attribute that is indexed and stored in this final representation
100  * structure. Finally, a new timestamp is obtained for these class
101  * statistics and they are stored to disk within the catalog structure
102  * for the last class representation.
103  */
104 int
105 xstats_update_statistics (THREAD_ENTRY * thread_p, OID * class_id_p, bool with_fullscan)
106 {
107  CLS_INFO *cls_info_p = NULL;
108  REPR_ID repr_id;
109  DISK_REPR *disk_repr_p = NULL;
110  DISK_ATTR *disk_attr_p = NULL;
111  BTREE_STATS *btree_stats_p = NULL;
112  OID dir_oid;
113  int npages, estimated_nobjs;
114  char *class_name = NULL;
115  int i, j;
116  OID *partitions = NULL;
117  int count = 0, error_code = NO_ERROR;
118  int lk_grant_code = 0;
120 
121  thread_p->push_resource_tracks ();
122 
123  OID_SET_NULL (&dir_oid);
124 
125  if (heap_get_class_name (thread_p, class_id_p, &class_name) != NO_ERROR || class_name == NULL)
126  {
127  /* something wrong. give up. */
128  ASSERT_ERROR_AND_SET (error_code);
129  thread_p->pop_resource_tracks ();
130 
131  return error_code;
132  }
133 
134  /* before go further, we should get the lock to disable updating schema */
135  lk_grant_code = lock_object (thread_p, class_id_p, oid_Root_class_oid, SCH_S_LOCK, LK_COND_LOCK);
136  if (lk_grant_code != LK_GRANTED)
137  {
138  error_code = ER_UPDATE_STAT_CANNOT_GET_LOCK;
139  er_set (ER_NOTIFICATION_SEVERITY, ARG_FILE_LINE, error_code, 1, class_name ? class_name : "*UNKNOWN-CLASS*");
140 
141  goto error;
142  }
143 
144  if (catalog_get_dir_oid_from_cache (thread_p, class_id_p, &dir_oid) != NO_ERROR)
145  {
146  goto error;
147  }
148 
149  catalog_access_info.class_oid = class_id_p;
150  catalog_access_info.dir_oid = &dir_oid;
151  catalog_access_info.class_name = class_name;
152  error_code = catalog_start_access_with_dir_oid (thread_p, &catalog_access_info, S_LOCK);
153  if (error_code != NO_ERROR)
154  {
155  goto error;
156  }
157 
158  cls_info_p = catalog_get_class_info (thread_p, class_id_p, &catalog_access_info);
159  if (cls_info_p == NULL)
160  {
161  goto error;
162  }
163 
164  (void) catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, NO_ERROR);
165 
167  class_name ? class_name : "*UNKNOWN-CLASS*", class_id_p->volid, class_id_p->pageid, class_id_p->slotid);
168 
169  /* if class information was not obtained */
170  if (cls_info_p->ci_hfid.vfid.fileid < 0 || cls_info_p->ci_hfid.vfid.volid < 0)
171  {
172  /* The class does not have a heap file (i.e. it has no instances); so no statistics can be obtained for this
173  * class; just set to 0 and return. */
174 
175  cls_info_p->ci_tot_pages = 0;
176  cls_info_p->ci_tot_objects = 0;
177 
178  error_code = catalog_start_access_with_dir_oid (thread_p, &catalog_access_info, X_LOCK);
179  if (error_code != NO_ERROR)
180  {
181  goto error;
182  }
183 
184  error_code = catalog_add_class_info (thread_p, class_id_p, cls_info_p, &catalog_access_info);
185  if (error_code != NO_ERROR)
186  {
187  goto error;
188  }
189 
190  goto end;
191  }
192 
193  error_code = partition_get_partition_oids (thread_p, class_id_p, &partitions, &count);
194  if (error_code != NO_ERROR)
195  {
196  goto error;
197  }
198 
199  if (count != 0)
200  {
201  /* Update statistics for all partitions and the partitioned class */
202  assert (partitions != NULL);
204  error_code = stats_update_partitioned_statistics (thread_p, class_id_p, partitions, count, with_fullscan);
205  db_private_free (thread_p, partitions);
206  if (error_code != NO_ERROR)
207  {
208  goto error;
209  }
210 
211  goto end;
212  }
213 
214  error_code = catalog_start_access_with_dir_oid (thread_p, &catalog_access_info, S_LOCK);
215  if (error_code != NO_ERROR)
216  {
217  goto error;
218  }
219 
220  if (catalog_get_last_representation_id (thread_p, class_id_p, &repr_id) != NO_ERROR)
221  {
222  goto error;
223  }
224 
225  disk_repr_p = catalog_get_representation (thread_p, class_id_p, repr_id, &catalog_access_info);
226  if (disk_repr_p == NULL)
227  {
228  goto error;
229  }
230  (void) catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, NO_ERROR);
231 
232  npages = estimated_nobjs = 0;
233 
234  /* do not use estimated npages, get correct info */
235  if (file_get_num_user_pages (thread_p, &(cls_info_p->ci_hfid.vfid), &npages) != NO_ERROR)
236  {
237  goto error;
238  }
239  assert (npages > 0);
240  cls_info_p->ci_tot_pages = MAX (npages, 0);
241 
242  estimated_nobjs = heap_estimate_num_objects (thread_p, &(cls_info_p->ci_hfid));
243  if (estimated_nobjs == -1)
244  {
245  /* cannot get estimates from the heap, use old info */
246  assert (cls_info_p->ci_tot_objects >= 0);
247  }
248  else
249  {
250  cls_info_p->ci_tot_objects = estimated_nobjs;
251  }
252 
253  /* update the index statistics for each attribute */
254 
255  for (i = 0; i < disk_repr_p->n_fixed + disk_repr_p->n_variable; i++)
256  {
257  if (i < disk_repr_p->n_fixed)
258  {
259  disk_attr_p = disk_repr_p->fixed + i;
260  }
261  else
262  {
263  disk_attr_p = disk_repr_p->variable + (i - disk_repr_p->n_fixed);
264  }
265 
266  for (j = 0, btree_stats_p = disk_attr_p->bt_stats; j < disk_attr_p->n_btstats; j++, btree_stats_p++)
267  {
268  assert_release (!BTID_IS_NULL (&btree_stats_p->btid));
269  assert_release (btree_stats_p->pkeys_size > 0);
270  assert_release (btree_stats_p->pkeys_size <= BTREE_STATS_PKEYS_NUM);
271 
272  if (btree_get_stats (thread_p, btree_stats_p, with_fullscan) != NO_ERROR)
273  {
274  goto error;
275  }
276 
277  assert_release (btree_stats_p->keys >= 0);
278  } /* for (j = 0; ...) */
279  } /* for (i = 0; ...) */
280 
281  error_code = catalog_start_access_with_dir_oid (thread_p, &catalog_access_info, X_LOCK);
282  if (error_code != NO_ERROR)
283  {
284  goto error;
285  }
286 
287  /* replace the current disk representation structure/information in the catalog with the newly computed statistics */
288  assert (!OID_ISNULL (&(cls_info_p->ci_rep_dir)));
289  error_code =
290  catalog_add_representation (thread_p, class_id_p, repr_id, disk_repr_p, &(cls_info_p->ci_rep_dir),
291  &catalog_access_info);
292  if (error_code != NO_ERROR)
293  {
294  goto error;
295  }
296 
297  cls_info_p->ci_time_stamp = stats_get_time_stamp ();
298 
299  error_code = catalog_add_class_info (thread_p, class_id_p, cls_info_p, &catalog_access_info);
300  if (error_code != NO_ERROR)
301  {
302  goto error;
303  }
304 
305 end:
306 
307  (void) catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, error_code);
308 
309  lock_unlock_object (thread_p, class_id_p, oid_Root_class_oid, SCH_S_LOCK, false);
310 
311  if (disk_repr_p)
312  {
314  }
315 
316  if (cls_info_p)
317  {
319  }
320 
322  class_name ? class_name : "*UNKNOWN-CLASS*", class_id_p->volid, class_id_p->pageid, class_id_p->slotid,
323  error_code);
324 
325  if (class_name)
326  {
327  free_and_init (class_name);
328  }
329 
330  thread_p->pop_resource_tracks ();
331 
332  return error_code;
333 
334 error:
335 
336  if (error_code == NO_ERROR && (error_code = er_errid ()) == NO_ERROR)
337  {
338  error_code = ER_FAILED;
339  }
340  goto end;
341 }
342 
343 /*
344  * xstats_update_all_statistics () - Updates the statistics
345  * for all the classes of the database
346  * return:
347  * with_fullscan(in): true iff WITH FULLSCAN
348  *
349  * Note: It performs this by getting the list of all classes existing in the
350  * database and their OID's from the catalog's class collection
351  * (maintained in an extendible hashing structure) and calling the
352  * "xstats_update_statistics" function for each one of the elements
353  * of this list one by one.
354  */
355 int
356 xstats_update_all_statistics (THREAD_ENTRY * thread_p, bool with_fullscan)
357 {
358  int error = NO_ERROR;
359  RECDES recdes = RECDES_INITIALIZER; /* Record descriptor for peeking object */
360  HFID root_hfid;
361  OID class_oid;
362 #if !defined(NDEBUG)
363  char *classname = NULL;
364 #endif
365  HEAP_SCANCACHE scan_cache;
367 
368  mvcc_snapshot = logtb_get_mvcc_snapshot (thread_p);
369  if (mvcc_snapshot == NULL)
370  {
371  return DISK_ERROR;
372  }
373 
374  /* Find every single class */
375 
376  if (boot_find_root_heap (&root_hfid) != NO_ERROR || HFID_IS_NULL (&root_hfid))
377  {
378  goto exit_on_error;
379  }
380 
381  if (heap_scancache_start (thread_p, &scan_cache, &root_hfid, oid_Root_class_oid, false, false, mvcc_snapshot) !=
382  NO_ERROR)
383  {
384  goto exit_on_error;
385  }
386 
387  class_oid.volid = root_hfid.vfid.volid;
388  class_oid.pageid = NULL_PAGEID;
389  class_oid.slotid = NULL_SLOTID;
390 
391  recdes.data = NULL;
392  while (heap_next (thread_p, &root_hfid, oid_Root_class_oid, &class_oid, &recdes, &scan_cache, COPY) == S_SUCCESS)
393  {
394 #if !defined(NDEBUG)
395  classname = or_class_name (&recdes);
396  assert (classname != NULL);
397  assert (strlen (classname) < 255);
398 #endif
399 
400  error = xstats_update_statistics (thread_p, &class_oid, with_fullscan);
401  if (error == ER_UPDATE_STAT_CANNOT_GET_LOCK || error == ER_SP_UNKNOWN_SLOTID)
402  {
403  /* continue with other classes */
404  er_clear ();
405  error = NO_ERROR;
406  }
407  else if (error != NO_ERROR)
408  {
409  break;
410  }
411  recdes.data = NULL;
412  } /* while (...) */
413 
414  /* End the scan cursor */
415  if (heap_scancache_end (thread_p, &scan_cache) != NO_ERROR)
416  {
417  goto exit_on_error;
418  }
419 
420  return error;
421 
422 exit_on_error:
423 
424  return DISK_ERROR;
425 }
426 
427 /*
428  * xstats_get_statistics_from_server () - Retrieves the class statistics
429  * return: buffer contaning class statistics, or NULL on error
430  * class_id(in): Identifier of the class
431  * timestamp(in):
432  * length(in): Length of the buffer
433  *
434  * Note: This function retrieves the statistics for the given class from the
435  * catalog manager and stores them into a buffer. Note that since the
436  * statistics are kept on the current (last) representation structure of
437  * the catalog, only this structure is retrieved. Note further that
438  * since the statistics are used only on the client side they are not
439  * put into a structure here on the server side (not even temporarily),
440  * but stored into a buffer area to be transmitted to the client side.
441  */
442 char *
443 xstats_get_statistics_from_server (THREAD_ENTRY * thread_p, OID * class_id_p, unsigned int time_stamp, int *length_p)
444 {
445  CLS_INFO *cls_info_p;
446  REPR_ID repr_id;
447  DISK_REPR *disk_repr_p;
448  DISK_ATTR *disk_attr_p;
449  BTREE_STATS *btree_stats_p;
450  OID dir_oid;
451  int npages, estimated_nobjs, max_unique_keys;
452  int i, j, k, size, n_attrs, tot_n_btstats, tot_key_info_size;
453  char *buf_p, *start_p;
454  int key_size;
455  int lk_grant_code;
457  bool use_stat_estimation = prm_get_bool_value (PRM_ID_USE_STAT_ESTIMATION);
458 
459  /* init */
460  cls_info_p = NULL;
461  disk_repr_p = NULL;
462 
463  thread_p->push_resource_tracks ();
464 
465  *length_p = -1;
466 
467  /* the lock on class to avoid changes of representation from rollbacked UPDATE statistics */
468  lk_grant_code = lock_object (thread_p, class_id_p, oid_Root_class_oid, SCH_S_LOCK, LK_UNCOND_LOCK);
469  if (lk_grant_code != LK_GRANTED)
470  {
471  char *class_name = NULL;
472 
473  if (heap_get_class_name (thread_p, class_id_p, &class_name) != NO_ERROR)
474  {
475  /* ignore */
476  er_clear ();
477  }
478 
480  class_name ? class_name : "*UNKNOWN-CLASS*");
481 
482  if (class_name != NULL)
483  {
484  free_and_init (class_name);
485  }
486  goto exit_on_error;
487  }
488 
489  if (catalog_get_dir_oid_from_cache (thread_p, class_id_p, &dir_oid) != NO_ERROR)
490  {
491  goto exit_on_error;
492  }
493 
494  catalog_access_info.class_oid = class_id_p;
495  catalog_access_info.dir_oid = &dir_oid;
496  if (catalog_start_access_with_dir_oid (thread_p, &catalog_access_info, S_LOCK) != NO_ERROR)
497  {
498  goto exit_on_error;
499  }
500 
501  cls_info_p = catalog_get_class_info (thread_p, class_id_p, &catalog_access_info);
502  if (cls_info_p == NULL)
503  {
504  goto exit_on_error;
505  }
506 
507  if (time_stamp > 0 && time_stamp >= cls_info_p->ci_time_stamp)
508  {
509  *length_p = 0;
510  goto exit_on_error;
511  }
512 
513  if (catalog_get_last_representation_id (thread_p, class_id_p, &repr_id) != NO_ERROR)
514  {
515  goto exit_on_error;
516  }
517 
518  disk_repr_p = catalog_get_representation (thread_p, class_id_p, repr_id, &catalog_access_info);
519  if (disk_repr_p == NULL)
520  {
521  goto exit_on_error;
522  }
523 
524  (void) catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, NO_ERROR);
525 
526  lock_unlock_object (thread_p, class_id_p, oid_Root_class_oid, SCH_S_LOCK, false);
527 
528  n_attrs = disk_repr_p->n_fixed + disk_repr_p->n_variable;
529 
530  tot_n_btstats = tot_key_info_size = 0;
531  for (i = 0; i < n_attrs; i++)
532  {
533  if (i < disk_repr_p->n_fixed)
534  {
535  disk_attr_p = disk_repr_p->fixed + i;
536  }
537  else
538  {
539  disk_attr_p = disk_repr_p->variable + (i - disk_repr_p->n_fixed);
540  }
541 
542  tot_n_btstats += disk_attr_p->n_btstats;
543  for (j = 0, btree_stats_p = disk_attr_p->bt_stats; j < disk_attr_p->n_btstats; j++, btree_stats_p++)
544  {
545  tot_key_info_size += or_packed_domain_size (btree_stats_p->key_type, 0);
546  assert (btree_stats_p->pkeys_size <= BTREE_STATS_PKEYS_NUM);
547  tot_key_info_size += (btree_stats_p->pkeys_size * OR_INT_SIZE); /* pkeys[] */
548  }
549  }
550 
551  size = (OR_INT_SIZE /* time_stamp of CLS_INFO */
552  + OR_INT_SIZE /* tot_objects of CLS_INFO */
553  + OR_INT_SIZE /* tot_pages of CLS_INFO */
554  + OR_INT_SIZE /* n_attrs from DISK_REPR */
555  + (OR_INT_SIZE /* id of DISK_ATTR */
556  + OR_INT_SIZE /* type of DISK_ATTR */
557  + OR_INT_SIZE /* n_btstats of DISK_ATTR */
558  ) * n_attrs); /* number of attributes */
559 
560  size += ((OR_BTID_ALIGNED_SIZE /* btid of BTREE_STATS */
561  + OR_INT_SIZE /* leafs of BTREE_STATS */
562  + OR_INT_SIZE /* pages of BTREE_STATS */
563  + OR_INT_SIZE /* height of BTREE_STATS */
564  + OR_INT_SIZE /* keys of BTREE_STATS */
565  + OR_INT_SIZE /* does the BTREE_STATS correspond to a function index */
566  ) * tot_n_btstats); /* total number of indexes */
567 
568  size += tot_key_info_size; /* key_type, pkeys[] of BTREE_STATS */
569 
570  size += OR_INT_SIZE; /* max_unique_keys */
571 
572  start_p = buf_p = (char *) malloc (size);
573  if (buf_p == NULL)
574  {
575  goto exit_on_error;
576  }
577  memset (start_p, 0, size);
578 
579  OR_PUT_INT (buf_p, cls_info_p->ci_time_stamp);
580  buf_p += OR_INT_SIZE;
581 
582  npages = estimated_nobjs = max_unique_keys = -1;
583 
584  assert (cls_info_p->ci_tot_objects >= 0);
585  assert (cls_info_p->ci_tot_pages >= 0);
586 
587  if (HFID_IS_NULL (&cls_info_p->ci_hfid))
588  {
589  /* The class does not have a heap file (i.e. it has no instances); so no statistics can be obtained for this
590  * class */
591  OR_PUT_INT (buf_p, cls_info_p->ci_tot_objects); /* #objects */
592  buf_p += OR_INT_SIZE;
593 
594  OR_PUT_INT (buf_p, cls_info_p->ci_tot_pages); /* #pages */
595  buf_p += OR_INT_SIZE;
596  }
597  else if (!use_stat_estimation)
598  {
599  /* use statistics info */
600  OR_PUT_INT (buf_p, cls_info_p->ci_tot_objects); /* #objects */
601  buf_p += OR_INT_SIZE;
602 
603  OR_PUT_INT (buf_p, MAX (cls_info_p->ci_tot_pages, 1)); /* #pages */
604  buf_p += OR_INT_SIZE;
605  }
606  else
607  {
608  /* use estimates from the heap since it is likely that its estimates are more accurate than the ones gathered at
609  * update statistics time */
610  estimated_nobjs = heap_estimate_num_objects (thread_p, &(cls_info_p->ci_hfid));
611  if (estimated_nobjs < 0)
612  {
613  /* cannot get estimates from the heap, use ones from the catalog */
614  estimated_nobjs = cls_info_p->ci_tot_objects;
615  }
616  else
617  {
618  /* heuristic is that big nobjs is better than small */
619  estimated_nobjs = MAX (estimated_nobjs, cls_info_p->ci_tot_objects);
620  }
621 
622  OR_PUT_INT (buf_p, estimated_nobjs); /* #objects */
623  buf_p += OR_INT_SIZE;
624 
625  /* do not use estimated npages, get correct info */
626  assert (!VFID_ISNULL (&cls_info_p->ci_hfid.vfid));
627  if (file_get_num_user_pages (thread_p, &cls_info_p->ci_hfid.vfid, &npages) != NO_ERROR)
628  {
629  int err;
630 
631  ASSERT_ERROR_AND_SET (err);
632  /* cannot get #pages from the heap, use ones from the catalog */
633  npages = cls_info_p->ci_tot_pages;
634  assert (0 < npages || err == ER_INTERRUPTED);
635  npages = MAX (npages, 1); /* safe-guard */
636  }
637  assert (npages > 0);
638 
639  OR_PUT_INT (buf_p, npages); /* #pages */
640  buf_p += OR_INT_SIZE;
641  }
642 
643  OR_PUT_INT (buf_p, n_attrs);
644  buf_p += OR_INT_SIZE;
645 
646  /* put the statistics information of each attribute to the buffer */
647  for (i = 0; i < n_attrs; i++)
648  {
649  if (i < disk_repr_p->n_fixed)
650  {
651  disk_attr_p = disk_repr_p->fixed + i;
652  }
653  else
654  {
655  disk_attr_p = disk_repr_p->variable + (i - disk_repr_p->n_fixed);
656  }
657 
658  OR_PUT_INT (buf_p, disk_attr_p->id);
659  buf_p += OR_INT_SIZE;
660 
661  OR_PUT_INT (buf_p, disk_attr_p->type);
662  buf_p += OR_INT_SIZE;
663 
664  OR_PUT_INT (buf_p, disk_attr_p->n_btstats);
665  buf_p += OR_INT_SIZE;
666 
667  for (j = 0, btree_stats_p = disk_attr_p->bt_stats; j < disk_attr_p->n_btstats; j++, btree_stats_p++)
668  {
669  /* collect maximum unique keys info */
670  if (xbtree_get_unique_pk (thread_p, &btree_stats_p->btid))
671  {
672  max_unique_keys = MAX (max_unique_keys, btree_stats_p->keys);
673  }
674 
675  OR_PUT_BTID (buf_p, &btree_stats_p->btid);
676  buf_p += OR_BTID_ALIGNED_SIZE;
677 
678  /* defense for not gathered statistics */
679  btree_stats_p->leafs = MAX (1, btree_stats_p->leafs);
680  btree_stats_p->pages = MAX (1, btree_stats_p->pages);
681  btree_stats_p->height = MAX (1, btree_stats_p->height);
682 
683  /* If the btree file has currently more pages than when we gathered statistics, assume that all growth happen
684  * at the leaf level. If the btree is smaller, we use the gathered statistics since the btree may have an
685  * external file (unknown at this level) to keep overflow keys. */
686  if (file_get_num_user_pages (thread_p, &btree_stats_p->btid.vfid, &npages) != NO_ERROR)
687  {
688  int err;
689 
690  /* what to do here? */
691  ASSERT_ERROR_AND_SET (err);
692  npages = btree_stats_p->pages;
693  assert (0 < npages || err == ER_INTERRUPTED);
694  npages = MAX (npages, 1); /* safe-guard */
695  }
696  assert (npages > 0);
697  if (npages > btree_stats_p->pages && use_stat_estimation)
698  {
699  OR_PUT_INT (buf_p, (btree_stats_p->leafs + (npages - btree_stats_p->pages)));
700  buf_p += OR_INT_SIZE;
701 
702  OR_PUT_INT (buf_p, npages);
703  buf_p += OR_INT_SIZE;
704  }
705  else
706  {
707  OR_PUT_INT (buf_p, btree_stats_p->leafs);
708  buf_p += OR_INT_SIZE;
709 
710  OR_PUT_INT (buf_p, btree_stats_p->pages);
711  buf_p += OR_INT_SIZE;
712  }
713 
714  OR_PUT_INT (buf_p, btree_stats_p->height);
715  buf_p += OR_INT_SIZE;
716 
717  OR_PUT_INT (buf_p, btree_stats_p->has_function);
718  buf_p += OR_INT_SIZE;
719 
720  /* check and handle with estimation, since pkeys[] is not gathered before update stats */
721  if (estimated_nobjs > 0 && use_stat_estimation)
722  {
723  /* is non-empty index */
724  btree_stats_p->keys = MAX (btree_stats_p->keys, 1);
725 
726  /* If the estimated objects from heap manager is greater than the estimate when the statistics were
727  * gathered, assume that the difference is in distinct keys. */
728  if (cls_info_p->ci_tot_objects > 0 && estimated_nobjs > cls_info_p->ci_tot_objects)
729  {
730  btree_stats_p->keys += (estimated_nobjs - cls_info_p->ci_tot_objects);
731  }
732  }
733 
734  OR_PUT_INT (buf_p, btree_stats_p->keys);
735  buf_p += OR_INT_SIZE;
736 
737  assert_release (btree_stats_p->leafs >= 1);
738  assert_release (btree_stats_p->pages >= 1);
739  assert_release (btree_stats_p->height >= 1);
740  assert_release (btree_stats_p->keys >= 0);
741 
742  buf_p = or_pack_domain (buf_p, btree_stats_p->key_type, 0, 0);
743 
744  /* get full key size */
745  if (TP_DOMAIN_TYPE (btree_stats_p->key_type) == DB_TYPE_MIDXKEY)
746  {
747  key_size = tp_domain_size (btree_stats_p->key_type->setdomain);
748  }
749  else
750  {
751  key_size = 1;
752  }
753  assert (key_size >= btree_stats_p->pkeys_size);
754 
755  assert (btree_stats_p->pkeys_size <= BTREE_STATS_PKEYS_NUM);
756  for (k = 0; k < btree_stats_p->pkeys_size; k++)
757  {
758  /* check and handle with estimation, since pkeys[] is not gathered before update stats */
759  if (estimated_nobjs > 0 && use_stat_estimation)
760  {
761  /* is non-empty index */
762  btree_stats_p->pkeys[k] = MAX (btree_stats_p->pkeys[k], 1);
763  }
764 
765  if (k + 1 == key_size)
766  {
767  /* this last pkeys must be equal to keys */
768  btree_stats_p->pkeys[k] = btree_stats_p->keys;
769  }
770 
771  OR_PUT_INT (buf_p, btree_stats_p->pkeys[k]);
772  buf_p += OR_INT_SIZE;
773  }
774  } /* for (j = 0, ...) */
775  }
776 
777  OR_PUT_INT (buf_p, max_unique_keys);
778  buf_p += OR_INT_SIZE;
779 
782 
783  *length_p = CAST_STRLEN (buf_p - start_p);
784 
785  thread_p->pop_resource_tracks ();
786 
787  return start_p;
788 
789 exit_on_error:
790 
791  if (catalog_access_info.access_started)
792  {
793  (void) catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, ER_FAILED);
794  }
795 
796  if (disk_repr_p)
797  {
799  }
800  if (cls_info_p)
801  {
803  }
804 
805  thread_p->pop_resource_tracks ();
806 
807  return NULL;
808 }
809 
810 #if defined(ENABLE_UNUSED_FUNCTION)
811 /*
812  * stats_compare_date () -
813  * return:
814  * date1(in): First date value
815  * date2(in): Second date value
816  *
817  * Note: This function compares two date values and returns an integer less
818  * than, equal to, or greater than 0, if the first one is less than,
819  * equal to, or greater than the second one, respectively.
820  */
821 static int
822 stats_compare_date (DB_DATE * date1_p, DB_DATE * date2_p)
823 {
824  return (*date1_p - *date2_p);
825 }
826 
827 /*
828  * stats_compare_time () -
829  * return:
830  * time1(in): First time value
831  * time2(in): Second time value
832  *
833  * Note: This function compares two time values and returns an integer less
834  * than, equal to, or greater than 0, if the first one is less than,
835  * equal to, or greater than the second one, respectively.
836  */
837 static int
838 stats_compare_time (DB_TIME * time1_p, DB_TIME * time2_p)
839 {
840  return (int) (*time1_p - *time2_p);
841 }
842 
843 /*
844  * stats_compare_utime () -
845  * return:
846  * utime1(in): First utime value
847  * utime2(in): Second utime value
848  *
849  * Note: This function compares two utime values and returns an integer less
850  * than, equal to, or greater than 0, if the first one is less than,
851  * equal to, or greater than the second one, respectively.
852  */
853 static int
854 stats_compare_utime (DB_UTIME * utime1_p, DB_UTIME * utime2_p)
855 {
856  return (int) (*utime1_p - *utime2_p);
857 }
858 
859 /*
860  * stats_compare_datetime () -
861  * return:
862  * datetime1(in): First datetime value
863  * datetime2(in): Second datetime value
864  *
865  * Note: This function compares two datetime values and returns an integer less
866  * than, equal to, or greater than 0, if the first one is less than,
867  * equal to, or greater than the second one, respectively.
868  */
869 static int
870 stats_compare_datetime (DB_DATETIME * datetime1_p, DB_DATETIME * datetime2_p)
871 {
872  if (datetime1_p->date < datetime2_p->date)
873  {
874  return -1;
875  }
876  else if (datetime1_p->date > datetime2_p->date)
877  {
878  return 1;
879  }
880  else if (datetime1_p->time < datetime2_p->time)
881  {
882  return -1;
883  }
884  else if (datetime1_p->time > datetime2_p->time)
885  {
886  return 1;
887  }
888  else
889  {
890  return 0;
891  }
892 }
893 
894 /*
895  * stats_compare_money () -
896  * return:
897  * mn1(in): First money value
898  * ,n2(in): Second money value
899  *
900  * Note: This function compares two money values and returns an integer less
901  * than, equal to, or greater than 0, if the first one is less than,
902  * equal to, or greater than the second one, respectively.
903  */
904 static int
905 stats_compare_money (DB_MONETARY * money1_p, DB_MONETARY * money2_p)
906 {
907  double comp_result = money1_p->amount - money2_p->amount;
908 
909  if (comp_result == 0.0)
910  {
911  return 0;
912  }
913  else if (comp_result < 0.0)
914  {
915  return -1;
916  }
917  else
918  {
919  return 1;
920  }
921 }
922 
923 /*
924  * qst_data_compare () -
925  * return:
926  * data1(in):
927  * data2(in):
928  * type(in):
929  */
930 static int
931 stats_compare_data (DB_DATA * data1_p, DB_DATA * data2_p, DB_TYPE type)
932 {
933  int status = 0;
934 
935  switch (type)
936  {
937  case DB_TYPE_INTEGER:
938  status = ((data1_p->i < data2_p->i) ? DB_LT : ((data1_p->i > data2_p->i) ? DB_GT : DB_EQ));
939  break;
940 
941  case DB_TYPE_BIGINT:
942  status = ((data1_p->bigint < data2_p->bigint) ? DB_LT : ((data1_p->bigint > data2_p->bigint) ? DB_GT : DB_EQ));
943  break;
944 
945  case DB_TYPE_SHORT:
946  status = ((data1_p->sh < data2_p->sh) ? DB_LT : ((data1_p->sh > data2_p->sh) ? DB_GT : DB_EQ));
947  break;
948 
949  case DB_TYPE_FLOAT:
950  status = ((data1_p->f < data2_p->f) ? DB_LT : ((data1_p->f > data2_p->f) ? DB_GT : DB_EQ));
951  break;
952 
953  case DB_TYPE_DOUBLE:
954  status = ((data1_p->d < data2_p->d) ? DB_LT : ((data1_p->d > data2_p->d) ? DB_GT : DB_EQ));
955  break;
956 
957  case DB_TYPE_DATE:
958  status = stats_compare_date (&data1_p->date, &data2_p->date);
959  break;
960 
961  case DB_TYPE_TIME:
962  status = stats_compare_time (&data1_p->time, &data2_p->time);
963  break;
964 
965  case DB_TYPE_TIMESTAMP:
967  status = stats_compare_utime (&data1_p->utime, &data2_p->utime);
968  break;
969 
970  case DB_TYPE_TIMESTAMPTZ:
971  status = stats_compare_utime (&data1_p->timestamptz.timestamp, &data2_p->timestamptz.timestamp);
972  break;
973 
974  case DB_TYPE_DATETIME:
975  case DB_TYPE_DATETIMELTZ:
976  status = stats_compare_datetime (&data1_p->datetime, &data2_p->datetime);
977  break;
978 
979  case DB_TYPE_DATETIMETZ:
980  status = stats_compare_datetime (&data1_p->datetimetz.datetime, &data2_p->datetimetz.datetime);
981  break;
982 
983  case DB_TYPE_MONETARY:
984  status = stats_compare_money (&data1_p->money, &data2_p->money);
985  break;
986 
987  default:
988  status = 0;
989  break;
990  }
991  return (status);
992 }
993 #endif
994 
995 /*
996  * stats_get_time_stamp () - returns the current system time
997  * return: current system time
998  */
999 unsigned int
1001 {
1002  time_t tloc;
1003 
1004  return (unsigned int) time (&tloc);
1005 }
1006 
1007 #if defined(CUBRID_DEBUG)
1008 /*
1009  * stats_dump_class_stats () - Dumps the given statistics about a class
1010  * return:
1011  * class_stats(in): statistics to be printed
1012  * fpp(in):
1013  */
1014 void
1015 stats_dump_class_statistics (CLASS_STATS * class_stats, FILE * fpp)
1016 {
1017  int i, j, k;
1018  const char *prefix = "";
1019  time_t tloc;
1020 
1021  if (class_stats == NULL)
1022  {
1023  return;
1024  }
1025 
1026  fprintf (fpp, "\nCLASS STATISTICS\n");
1027  fprintf (fpp, "****************\n");
1028  tloc = (time_t) class_stats->time_stamp;
1029  fprintf (fpp, " Timestamp: %s", ctime (&tloc));
1030  fprintf (fpp, " Total Pages in Class Heap: %d\n", class_stats->heap_num_pages);
1031  fprintf (fpp, " Total Objects: %d\n", class_stats->heap_num_objects);
1032  fprintf (fpp, " Number of attributes: %d\n", class_stats->n_attrs);
1033 
1034  for (i = 0; i < class_stats->n_attrs; i++)
1035  {
1036  fprintf (fpp, "\n Attribute :\n");
1037  fprintf (fpp, " id: %d\n", class_stats->attr_stats[i].id);
1038  fprintf (fpp, " Type: ");
1039 
1040  switch (class_stats->attr_stats[i].type)
1041  {
1042  case DB_TYPE_INTEGER:
1043  fprintf (fpp, "DB_TYPE_INTEGER \n");
1044  break;
1045 
1046  case DB_TYPE_BIGINT:
1047  fprintf (fpp, "DB_TYPE_BIGINT \n");
1048  break;
1049 
1050  case DB_TYPE_SHORT:
1051  fprintf (fpp, "DB_TYPE_SHORT \n");
1052  break;
1053 
1054  case DB_TYPE_FLOAT:
1055  fprintf (fpp, "DB_TYPE_FLOAT \n");
1056  break;
1057 
1058  case DB_TYPE_DOUBLE:
1059  fprintf (fpp, "DB_TYPE_DOUBLE \n");
1060  break;
1061 
1062  case DB_TYPE_STRING:
1063  fprintf (fpp, "DB_TYPE_STRING \n");
1064  break;
1065 
1066  case DB_TYPE_OBJECT:
1067  fprintf (fpp, "DB_TYPE_OBJECT \n");
1068  break;
1069 
1070  case DB_TYPE_SET:
1071  fprintf (fpp, "DB_TYPE_SET \n");
1072  break;
1073 
1074  case DB_TYPE_JSON:
1075  fprintf (fpp, "DB_TYPE_JSON \n");
1076  break;
1077 
1078  case DB_TYPE_MULTISET:
1079  fprintf (fpp, "DB_TYPE_MULTISET \n");
1080  break;
1081 
1082  case DB_TYPE_SEQUENCE:
1083  fprintf (fpp, "DB_TYPE_SEQUENCE \n");
1084  break;
1085 
1086  case DB_TYPE_TIME:
1087  fprintf (fpp, "DB_TYPE_TIME \n");
1088  break;
1089 
1090  case DB_TYPE_TIMESTAMP:
1091  fprintf (fpp, "DB_TYPE_TIMESTAMP \n");
1092  break;
1093 
1094  case DB_TYPE_TIMESTAMPLTZ:
1095  fprintf (fpp, "DB_TYPE_TIMESTAMPLTZ \n");
1096  break;
1097 
1098  case DB_TYPE_TIMESTAMPTZ:
1099  fprintf (fpp, "DB_TYPE_TIMESTAMPTZ \n");
1100  break;
1101 
1102  case DB_TYPE_DATETIME:
1103  fprintf (fpp, "DB_TYPE_DATETIME \n");
1104  break;
1105 
1106  case DB_TYPE_DATETIMELTZ:
1107  fprintf (fpp, "DB_TYPE_DATETIMELTZ \n");
1108  break;
1109 
1110  case DB_TYPE_DATETIMETZ:
1111  fprintf (fpp, "DB_TYPE_DATETIMETZ \n");
1112  break;
1113 
1114  case DB_TYPE_MONETARY:
1115  fprintf (fpp, "DB_TYPE_MONETARY \n");
1116  break;
1117 
1118  case DB_TYPE_DATE:
1119  fprintf (fpp, "DB_TYPE_DATE \n");
1120  break;
1121 
1122  case DB_TYPE_BLOB:
1123  fprintf (fpp, "DB_TYPE_BLOB \n");
1124  break;
1125 
1126  case DB_TYPE_CLOB:
1127  fprintf (fpp, "DB_TYPE_CLOB \n");
1128  break;
1129 
1130  case DB_TYPE_VARIABLE:
1131  fprintf (fpp, "DB_TYPE_VARIABLE \n");
1132  break;
1133 
1134  case DB_TYPE_SUB:
1135  fprintf (fpp, "DB_TYPE_SUB \n");
1136  break;
1137 
1138  case DB_TYPE_POINTER:
1139  fprintf (fpp, "DB_TYPE_POINTER \n");
1140  break;
1141 
1142  case DB_TYPE_NULL:
1143  fprintf (fpp, "DB_TYPE_NULL \n");
1144  break;
1145 
1146  case DB_TYPE_NUMERIC:
1147  fprintf (fpp, "DB_TYPE_NUMERIC \n");
1148  break;
1149 
1150  case DB_TYPE_BIT:
1151  fprintf (fpp, "DB_TYPE_BIT \n");
1152  break;
1153 
1154  case DB_TYPE_VARBIT:
1155  fprintf (fpp, "DB_TYPE_VARBIT \n");
1156  break;
1157 
1158  case DB_TYPE_CHAR:
1159  fprintf (fpp, "DB_TYPE_CHAR \n");
1160  break;
1161 
1162  case DB_TYPE_NCHAR:
1163  fprintf (fpp, "DB_TYPE_NCHAR \n");
1164  break;
1165 
1166  case DB_TYPE_VARNCHAR:
1167  fprintf (fpp, "DB_TYPE_VARNCHAR \n");
1168  break;
1169 
1170  default:
1171  break;
1172  }
1173 
1174  fprintf (fpp, " BTree statistics:\n");
1175 
1176  for (j = 0; j < class_stats->attr_stats[i].n_btstats; j++)
1177  {
1178  BTREE_STATS *bt_statsp = &class_stats->attr_stats[i].bt_stats[j];
1179  fprintf (fpp, " BTID: { %d , %d }\n", bt_statsp->btid.vfid.volid, bt_statsp->btid.vfid.fileid);
1180  fprintf (fpp, " Cardinality: %d (", bt_statsp->keys);
1181 
1182  prefix = "";
1183  assert (bt_statsp->pkeys_size <= BTREE_STATS_PKEYS_NUM);
1184  for (k = 0; k < bt_statsp->pkeys_size; k++)
1185  {
1186  fprintf (fpp, "%s%d", prefix, bt_statsp->pkeys[k]);
1187  prefix = ",";
1188  }
1189 
1190  fprintf (fpp, ") ,");
1191  fprintf (fpp, " Total Pages: %d , Leaf Pages: %d , Height: %d\n", bt_statsp->pages, bt_statsp->leafs,
1192  bt_statsp->height);
1193  }
1194  fprintf (fpp, "\n");
1195  }
1196 
1197  fprintf (fpp, "\n\n");
1198 }
1199 #endif /* CUBRID_DEBUG */
1200 
1201 /*
1202  * stats_update_partitioned_statistics () - compute statistics for a partitioned class
1203  * return : error code or NO_ERROR
1204  * thread_p (in) :
1205  * class_id_p (in) : oid of the partitioned class
1206  * partitions (in) : oids of partitions
1207  * int partitions_count (in) : number of partitions
1208  * with_fullscan(in): true iff WITH FULLSCAN
1209  *
1210  * Note: Since, during plan generation we only have access to the partitioned
1211  * class, we have to keep an estimate of average statistics in this class. We
1212  * are using the average because we consider the case in which only one
1213  * partition is pruned to be the most common case.
1214  *
1215  * The average is computed as the mean (1 + coefficient of variation). We
1216  * use this coefficient to account for situations in which an index is not
1217  * balanced in the hierarchy (i.e: has lots of keys in some partitions but
1218  * very few keys in others). This type of distribution should be considered
1219  * worse than a balanced distribution since we don't know which partition
1220  * will be used in the query.
1221  */
1222 static int
1223 stats_update_partitioned_statistics (THREAD_ENTRY * thread_p, OID * class_id_p, OID * partitions, int partitions_count,
1224  bool with_fullscan)
1225 {
1226  int i, j, k, btree_iter, m;
1227  int error = NO_ERROR;
1228  CLS_INFO *cls_info_p = NULL;
1229  CLS_INFO *subcls_info = NULL;
1230  DISK_REPR *disk_repr_p = NULL, *subcls_disk_rep = NULL;
1231  REPR_ID repr_id = NULL_REPRID, subcls_repr_id = NULL_REPRID;
1232  DISK_ATTR *disk_attr_p = NULL, *subcls_attr_p = NULL;
1233  BTREE_STATS *btree_stats_p = NULL;
1234  int n_btrees = 0;
1235  PARTITION_STATS_ACUMULATOR *mean = NULL, *stddev = NULL;
1236  OR_CLASSREP *cls_rep = NULL;
1237  OR_CLASSREP *subcls_rep = NULL;
1238  int cls_idx_cache = 0, subcls_idx_cache = 0;
1240  CATALOG_ACCESS_INFO part_catalog_access_info = CATALOG_ACCESS_INFO_INITIALIZER;
1241  OID dir_oid;
1242  OID part_dir_oid;
1243 
1244  assert_release (class_id_p != NULL);
1245  assert_release (partitions != NULL);
1246  assert_release (partitions_count > 0);
1247 
1248  for (i = 0; i < partitions_count; i++)
1249  {
1250  error = xstats_update_statistics (thread_p, &partitions[i], with_fullscan);
1251  if (error != NO_ERROR)
1252  {
1253  goto cleanup;
1254  }
1255  }
1256 
1257  error = catalog_get_dir_oid_from_cache (thread_p, class_id_p, &dir_oid);
1258  if (error != NO_ERROR)
1259  {
1260  goto cleanup;
1261  }
1262 
1263  catalog_access_info.class_oid = class_id_p;
1264  catalog_access_info.dir_oid = &dir_oid;
1265  error = catalog_start_access_with_dir_oid (thread_p, &catalog_access_info, S_LOCK);
1266  if (error != NO_ERROR)
1267  {
1268  goto cleanup;
1269  }
1270 
1271  cls_info_p = catalog_get_class_info (thread_p, class_id_p, &catalog_access_info);
1272  if (cls_info_p == NULL)
1273  {
1274  ASSERT_ERROR_AND_SET (error);
1275  goto cleanup;
1276  }
1277 
1278  error = catalog_get_last_representation_id (thread_p, class_id_p, &repr_id);
1279  if (error != NO_ERROR)
1280  {
1281  goto cleanup;
1282  }
1283 
1284  cls_info_p->ci_tot_pages = 0;
1285  cls_info_p->ci_tot_objects = 0;
1286 
1287  disk_repr_p = catalog_get_representation (thread_p, class_id_p, repr_id, &catalog_access_info);
1288  if (disk_repr_p == NULL)
1289  {
1290  ASSERT_ERROR_AND_SET (error);
1291  goto cleanup;
1292  }
1293 
1294  (void) catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, NO_ERROR);
1295 
1296  /* partitions_count number of btree_stats we will need to use */
1297  n_btrees = 0;
1298  for (i = 0; i < disk_repr_p->n_fixed + disk_repr_p->n_variable; i++)
1299  {
1300  if (i < disk_repr_p->n_fixed)
1301  {
1302  disk_attr_p = disk_repr_p->fixed + i;
1303  }
1304  else
1305  {
1306  disk_attr_p = disk_repr_p->variable + (i - disk_repr_p->n_fixed);
1307  }
1308 
1309  for (j = 0, btree_stats_p = disk_attr_p->bt_stats; j < disk_attr_p->n_btstats; j++, btree_stats_p++)
1310  {
1311  n_btrees++;
1312  }
1313  }
1314 
1315  if (n_btrees == 0)
1316  {
1317  /* We're not really interested in this */
1318  error = NO_ERROR;
1319  goto cleanup;
1320  }
1321 
1322  mean = (PARTITION_STATS_ACUMULATOR *) db_private_alloc (thread_p, n_btrees * sizeof (PARTITION_STATS_ACUMULATOR));
1323  if (mean == NULL)
1324  {
1325  error = ER_FAILED;
1326  goto cleanup;
1327  }
1328 
1329  stddev = (PARTITION_STATS_ACUMULATOR *) db_private_alloc (thread_p, n_btrees * sizeof (PARTITION_STATS_ACUMULATOR));
1330  if (stddev == NULL)
1331  {
1332  error = ER_FAILED;
1333  goto cleanup;
1334  }
1335 
1336  memset (mean, 0, n_btrees * sizeof (PARTITION_STATS_ACUMULATOR));
1337  memset (stddev, 0, n_btrees * sizeof (PARTITION_STATS_ACUMULATOR));
1338 
1339  /* initialize pkeys */
1340  btree_iter = 0;
1341  for (i = 0; i < disk_repr_p->n_fixed + disk_repr_p->n_variable; i++)
1342  {
1343  if (i < disk_repr_p->n_fixed)
1344  {
1345  disk_attr_p = disk_repr_p->fixed + i;
1346  }
1347  else
1348  {
1349  disk_attr_p = disk_repr_p->variable + (i - disk_repr_p->n_fixed);
1350  }
1351 
1352  for (j = 0, btree_stats_p = disk_attr_p->bt_stats; j < disk_attr_p->n_btstats; j++, btree_stats_p++)
1353  {
1354  mean[btree_iter].pkeys_size = btree_stats_p->pkeys_size;
1355  mean[btree_iter].pkeys =
1356  (double *) db_private_alloc (thread_p, mean[btree_iter].pkeys_size * sizeof (double));
1357  if (mean[btree_iter].pkeys == NULL)
1358  {
1359  error = ER_FAILED;
1360  goto cleanup;
1361  }
1362  memset (mean[btree_iter].pkeys, 0, mean[btree_iter].pkeys_size * sizeof (double));
1363 
1364  stddev[btree_iter].pkeys_size = btree_stats_p->pkeys_size;
1365  stddev[btree_iter].pkeys =
1366  (double *) db_private_alloc (thread_p, mean[btree_iter].pkeys_size * sizeof (double));
1367  if (stddev[btree_iter].pkeys == NULL)
1368  {
1369  error = ER_FAILED;
1370  goto cleanup;
1371  }
1372  memset (stddev[btree_iter].pkeys, 0, mean[btree_iter].pkeys_size * sizeof (double));
1373  btree_iter++;
1374  }
1375  }
1376 
1377  /* Compute class statistics: For each btree compute the mean, standard deviation and coefficient of variation. The
1378  * global statistics for each btree will be the mean * (1 + cv). We do this so that the optimizer will pick the tree
1379  * with the lowest dispersion. Since partitions and partitioned class have the same indexes but not stored in the
1380  * same order, we will use class representations to match inherited indexes from partitions to the indexes in the
1381  * partitioned class class. */
1382  cls_rep = heap_classrepr_get (thread_p, class_id_p, NULL, NULL_REPRID, &cls_idx_cache);
1383  if (cls_rep == NULL)
1384  {
1385  error = ER_FAILED;
1386  goto cleanup;
1387  }
1388 
1389  for (i = 0; i < partitions_count; i++)
1390  {
1391  /* clean subclass loaded in previous iteration */
1392  if (subcls_info != NULL)
1393  {
1394  catalog_free_class_info_and_init (subcls_info);
1395  }
1396  if (subcls_disk_rep != NULL)
1397  {
1398  catalog_free_representation_and_init (subcls_disk_rep);
1399  }
1400  if (subcls_rep != NULL)
1401  {
1402  heap_classrepr_free_and_init (subcls_rep, &subcls_idx_cache);
1403  }
1404 
1405  if (catalog_get_dir_oid_from_cache (thread_p, &partitions[i], &part_dir_oid) != NO_ERROR)
1406  {
1407  assert (er_errid () != NO_ERROR);
1408  error = er_errid ();
1409  goto cleanup;
1410  }
1411 
1412  part_catalog_access_info.class_oid = &partitions[i];
1413  part_catalog_access_info.dir_oid = &part_dir_oid;
1414  if (catalog_start_access_with_dir_oid (thread_p, &part_catalog_access_info, S_LOCK) != NO_ERROR)
1415  {
1416  ASSERT_ERROR_AND_SET (error);
1417  goto cleanup;
1418  }
1419 
1420  /* load new subclass */
1421  subcls_info = catalog_get_class_info (thread_p, &partitions[i], &part_catalog_access_info);
1422  if (subcls_info == NULL)
1423  {
1424  ASSERT_ERROR_AND_SET (error);
1425  goto cleanup;
1426  }
1427  cls_info_p->ci_tot_pages += subcls_info->ci_tot_pages;
1428  cls_info_p->ci_tot_objects += subcls_info->ci_tot_objects;
1429 
1430  /* get disk repr for subclass */
1431  error = catalog_get_last_representation_id (thread_p, &partitions[i], &subcls_repr_id);
1432  if (error != NO_ERROR)
1433  {
1434  goto cleanup;
1435  }
1436 
1437  subcls_disk_rep = catalog_get_representation (thread_p, &partitions[i], subcls_repr_id,
1438  &part_catalog_access_info);
1439  if (subcls_disk_rep == NULL)
1440  {
1441  ASSERT_ERROR_AND_SET (error);
1442  goto cleanup;
1443  }
1444 
1445  (void) catalog_end_access_with_dir_oid (thread_p, &part_catalog_access_info, NO_ERROR);
1446 
1447  subcls_rep = heap_classrepr_get (thread_p, &partitions[i], NULL, NULL_REPRID, &subcls_idx_cache);
1448  if (subcls_rep == NULL)
1449  {
1450  error = ER_FAILED;
1451  goto cleanup;
1452  }
1453 
1454  /* add partition information to the accumulators and also update min/max values for partitioned class disk
1455  * representation */
1456  btree_iter = 0;
1457  for (j = 0; j < subcls_disk_rep->n_fixed + subcls_disk_rep->n_variable; j++)
1458  {
1459  if (j < subcls_disk_rep->n_fixed)
1460  {
1461  subcls_attr_p = subcls_disk_rep->fixed + j;
1462  disk_attr_p = disk_repr_p->fixed + j;
1463  }
1464  else
1465  {
1466  subcls_attr_p = subcls_disk_rep->variable + (j - subcls_disk_rep->n_fixed);
1467  disk_attr_p = disk_repr_p->variable + (j - disk_repr_p->n_fixed);
1468  }
1469 
1470  /* check for partitions schema changes are not yet finished */
1471  if (subcls_attr_p->id != disk_attr_p->id || subcls_attr_p->n_btstats != disk_attr_p->n_btstats)
1472  {
1473  error = NO_ERROR;
1474  goto cleanup;
1475  }
1476 
1477  assert_release (subcls_attr_p->id == disk_attr_p->id);
1478  assert_release (subcls_attr_p->n_btstats == disk_attr_p->n_btstats);
1479 
1480  for (k = 0, btree_stats_p = disk_attr_p->bt_stats; k < disk_attr_p->n_btstats; k++, btree_stats_p++)
1481  {
1482  const BTREE_STATS *subcls_stats;
1483 
1484  subcls_stats = stats_find_inherited_index_stats (cls_rep, subcls_rep, subcls_attr_p,
1485  &btree_stats_p->btid);
1486  if (subcls_stats == NULL)
1487  {
1488  error = ER_FAILED;
1489  goto cleanup;
1490  }
1491 
1492  mean[btree_iter].leafs += subcls_stats->leafs;
1493 
1494  mean[btree_iter].pages += subcls_stats->pages;
1495 
1496  mean[btree_iter].height += subcls_stats->height;
1497 
1498  mean[btree_iter].keys += subcls_stats->keys;
1499 
1500  assert (subcls_stats->pkeys_size <= BTREE_STATS_PKEYS_NUM);
1501  for (m = 0; m < subcls_stats->pkeys_size; m++)
1502  {
1503  mean[btree_iter].pkeys[m] += subcls_stats->pkeys[m];
1504  }
1505 
1506  btree_iter++;
1507  }
1508  }
1509  }
1510 
1511  /* compute actual mean */
1512  for (btree_iter = 0; btree_iter < n_btrees; btree_iter++)
1513  {
1514  mean[btree_iter].leafs /= partitions_count;
1515 
1516  mean[btree_iter].pages /= partitions_count;
1517 
1518  mean[btree_iter].height /= partitions_count;
1519 
1520  mean[btree_iter].keys /= partitions_count;
1521 
1522  assert (mean[btree_iter].pkeys_size <= BTREE_STATS_PKEYS_NUM);
1523  for (m = 0; m < mean[btree_iter].pkeys_size; m++)
1524  {
1525  mean[btree_iter].pkeys[m] /= partitions_count;
1526  }
1527  }
1528 
1529  for (i = 0; i < partitions_count; i++)
1530  {
1531  OID part_dir_oid;
1532 
1533  /* clean subclass loaded in previous iteration */
1534  if (subcls_disk_rep != NULL)
1535  {
1536  catalog_free_representation_and_init (subcls_disk_rep);
1537  }
1538  if (subcls_rep != NULL)
1539  {
1540  heap_classrepr_free_and_init (subcls_rep, &subcls_idx_cache);
1541  }
1542 
1543  if (catalog_get_dir_oid_from_cache (thread_p, &partitions[i], &part_dir_oid) != NO_ERROR)
1544  {
1545  ASSERT_ERROR_AND_SET (error);
1546  goto cleanup;
1547  }
1548 
1549  part_catalog_access_info.class_oid = &partitions[i];
1550  part_catalog_access_info.dir_oid = &part_dir_oid;
1551  if (catalog_start_access_with_dir_oid (thread_p, &part_catalog_access_info, S_LOCK) != NO_ERROR)
1552  {
1553  ASSERT_ERROR_AND_SET (error);
1554  goto cleanup;
1555  }
1556 
1557  /* get disk repr for subclass */
1558  error = catalog_get_last_representation_id (thread_p, &partitions[i], &subcls_repr_id);
1559  if (error != NO_ERROR)
1560  {
1561  goto cleanup;
1562  }
1563 
1564  subcls_disk_rep = catalog_get_representation (thread_p, &partitions[i], subcls_repr_id,
1565  &part_catalog_access_info);
1566  if (subcls_disk_rep == NULL)
1567  {
1568  ASSERT_ERROR_AND_SET (error);
1569  goto cleanup;
1570  }
1571  (void) catalog_end_access_with_dir_oid (thread_p, &part_catalog_access_info, NO_ERROR);
1572 
1573  subcls_rep = heap_classrepr_get (thread_p, &partitions[i], NULL, NULL_REPRID, &subcls_idx_cache);
1574  if (subcls_rep == NULL)
1575  {
1576  error = ER_FAILED;
1577  goto cleanup;
1578  }
1579 
1580  /* add partition information to the accumulators */
1581  btree_iter = 0;
1582  for (j = 0; j < subcls_disk_rep->n_fixed + subcls_disk_rep->n_variable; j++)
1583  {
1584  if (j < subcls_disk_rep->n_fixed)
1585  {
1586  subcls_attr_p = subcls_disk_rep->fixed + j;
1587  disk_attr_p = disk_repr_p->fixed + j;
1588  }
1589  else
1590  {
1591  subcls_attr_p = subcls_disk_rep->variable + (j - subcls_disk_rep->n_fixed);
1592  disk_attr_p = disk_repr_p->variable + (j - disk_repr_p->n_fixed);
1593  }
1594 
1595  /* check for partitions schema changes are not yet finished */
1596  if (subcls_attr_p->id != disk_attr_p->id || subcls_attr_p->n_btstats != disk_attr_p->n_btstats)
1597  {
1598  assert (false); /* is impossible */
1599  error = NO_ERROR;
1600  goto cleanup;
1601  }
1602 
1603  assert_release (subcls_attr_p->id == disk_attr_p->id);
1604  assert_release (subcls_attr_p->n_btstats == disk_attr_p->n_btstats);
1605 
1606  for (k = 0, btree_stats_p = disk_attr_p->bt_stats; k < disk_attr_p->n_btstats; k++, btree_stats_p++)
1607  {
1608  const BTREE_STATS *subcls_stats;
1609 
1610  subcls_stats = stats_find_inherited_index_stats (cls_rep, subcls_rep, subcls_attr_p,
1611  &btree_stats_p->btid);
1612  if (subcls_stats == NULL)
1613  {
1614  error = ER_FAILED;
1615  goto cleanup;
1616  }
1617 
1618  stddev[btree_iter].leafs += SQUARE (btree_stats_p->leafs - mean[btree_iter].leafs);
1619 
1620  stddev[btree_iter].pages += SQUARE (subcls_stats->pages - mean[btree_iter].pages);
1621 
1622  stddev[btree_iter].height += SQUARE (subcls_stats->height - mean[btree_iter].height);
1623 
1624  stddev[btree_iter].keys += SQUARE (subcls_stats->keys - mean[btree_iter].keys);
1625 
1626  assert (subcls_stats->pkeys_size <= BTREE_STATS_PKEYS_NUM);
1627  for (m = 0; m < subcls_stats->pkeys_size; m++)
1628  {
1629  stddev[btree_iter].pkeys[m] += SQUARE (subcls_stats->pkeys[m] - mean[btree_iter].pkeys[m]);
1630  }
1631 
1632  btree_iter++;
1633  }
1634  }
1635  }
1636 
1637  for (btree_iter = 0; btree_iter < n_btrees; btree_iter++)
1638  {
1639  stddev[btree_iter].leafs = sqrt (stddev[btree_iter].leafs / partitions_count);
1640 
1641  stddev[btree_iter].pages = sqrt (stddev[btree_iter].pages / partitions_count);
1642 
1643  stddev[btree_iter].height = sqrt (stddev[btree_iter].height / partitions_count);
1644 
1645  stddev[btree_iter].keys = sqrt (stddev[btree_iter].keys / partitions_count);
1646 
1647  assert (mean[btree_iter].pkeys_size <= BTREE_STATS_PKEYS_NUM);
1648  for (m = 0; m < mean[btree_iter].pkeys_size; m++)
1649  {
1650  stddev[btree_iter].pkeys[m] = sqrt (stddev[btree_iter].pkeys[m] / partitions_count);
1651  }
1652  }
1653 
1654  /* compute new statistics */
1655  btree_iter = 0;
1656  for (i = 0; i < disk_repr_p->n_fixed + disk_repr_p->n_variable; i++)
1657  {
1658  if (i < disk_repr_p->n_fixed)
1659  {
1660  disk_attr_p = disk_repr_p->fixed + i;
1661  }
1662  else
1663  {
1664  disk_attr_p = disk_repr_p->variable + (i - disk_repr_p->n_fixed);
1665  }
1666 
1667  for (j = 0, btree_stats_p = disk_attr_p->bt_stats; j < disk_attr_p->n_btstats; j++, btree_stats_p++)
1668  {
1669  if (mean[btree_iter].leafs != 0)
1670  {
1671  btree_stats_p->leafs =
1672  (int) (mean[btree_iter].leafs * (1 + stddev[btree_iter].leafs / mean[btree_iter].leafs));
1673  }
1674  if (mean[btree_iter].pages != 0)
1675  {
1676  btree_stats_p->pages =
1677  (int) (mean[btree_iter].pages * (1 + stddev[btree_iter].pages / mean[btree_iter].pages));
1678  }
1679  if (mean[btree_iter].height != 0)
1680  {
1681  btree_stats_p->height =
1682  (int) (mean[btree_iter].height * (1 + stddev[btree_iter].height / mean[btree_iter].height));
1683  }
1684  if (mean[btree_iter].keys != 0)
1685  {
1686  btree_stats_p->keys =
1687  (int) (mean[btree_iter].keys * (1 + stddev[btree_iter].keys / mean[btree_iter].keys));
1688  }
1689 
1690  assert (mean[btree_iter].pkeys_size <= BTREE_STATS_PKEYS_NUM);
1691  for (m = 0; m < mean[btree_iter].pkeys_size; m++)
1692  {
1693  if (mean[btree_iter].pkeys[m] != 0)
1694  {
1695  btree_stats_p->pkeys[m] =
1696  (int) (mean[btree_iter].pkeys[m] * (1 + stddev[btree_iter].pkeys[m] / mean[btree_iter].pkeys[m]));
1697  }
1698  }
1699  btree_iter++;
1700  }
1701  }
1702 
1703  error = catalog_start_access_with_dir_oid (thread_p, &catalog_access_info, X_LOCK);
1704  if (error != NO_ERROR)
1705  {
1706  goto cleanup;
1707  }
1708 
1709  /* replace the current disk representation structure/information in the catalog with the newly computed statistics */
1710  assert (!OID_ISNULL (&(cls_info_p->ci_rep_dir)));
1711  error = catalog_add_representation (thread_p, class_id_p, repr_id, disk_repr_p, &(cls_info_p->ci_rep_dir),
1712  &catalog_access_info);
1713  if (error != NO_ERROR)
1714  {
1715  goto cleanup;
1716  }
1717 
1718  cls_info_p->ci_time_stamp = stats_get_time_stamp ();
1719 
1720  error = catalog_add_class_info (thread_p, class_id_p, cls_info_p, &catalog_access_info);
1721 
1722 cleanup:
1723  (void) catalog_end_access_with_dir_oid (thread_p, &catalog_access_info, error);
1724  (void) catalog_end_access_with_dir_oid (thread_p, &part_catalog_access_info, error);
1725 
1726  if (cls_rep != NULL)
1727  {
1728  heap_classrepr_free_and_init (cls_rep, &cls_idx_cache);
1729  }
1730  if (subcls_rep != NULL)
1731  {
1732  heap_classrepr_free_and_init (subcls_rep, &subcls_idx_cache);
1733  }
1734  if (mean != NULL)
1735  {
1736  for (i = 0; i < n_btrees; i++)
1737  {
1738  if (mean[i].pkeys != NULL)
1739  {
1740  db_private_free_and_init (thread_p, mean[i].pkeys);
1741  }
1742  }
1743  db_private_free_and_init (thread_p, mean);
1744  }
1745  if (stddev != NULL)
1746  {
1747  for (i = 0; i < n_btrees; i++)
1748  {
1749  if (stddev[i].pkeys != NULL)
1750  {
1751  db_private_free (thread_p, stddev[i].pkeys);
1752  }
1753  }
1754  db_private_free (thread_p, stddev);
1755  }
1756  if (subcls_info)
1757  {
1758  catalog_free_class_info_and_init (subcls_info);
1759  }
1760  if (subcls_disk_rep != NULL)
1761  {
1762  catalog_free_representation_and_init (subcls_disk_rep);
1763  }
1764  if (cls_info_p != NULL)
1765  {
1766  catalog_free_class_info_and_init (cls_info_p);
1767  }
1768  if (disk_repr_p != NULL)
1769  {
1771  }
1772 
1773  return error;
1774 }
1775 
1776 /*
1777  * stats_find_inherited_index_stats () - find the btree statistics corresponding to an index in a subclass
1778  * return : btree statistics
1779  * cls_rep (in) : superclass representation
1780  * subcls_rep (in) : subclass representation
1781  * subcls_attr (in): subclass attribute representation which contains the
1782  * statistics
1783  * cls_btid (in) : BTID of the index in the superclass
1784  */
1785 const BTREE_STATS *
1786 stats_find_inherited_index_stats (OR_CLASSREP * cls_rep, OR_CLASSREP * subcls_rep, DISK_ATTR * subcls_attr,
1787  BTID * cls_btid)
1788 {
1789  int i;
1790  const char *cls_btname = NULL;
1791  const BTID *subcls_btid = NULL;
1792  BTREE_STATS *btstats = NULL;
1793 
1794  /* find the index representation in the superclass */
1795  for (i = 0; i < cls_rep->n_indexes; i++)
1796  {
1797  if (BTID_IS_EQUAL (&cls_rep->indexes[i].btid, cls_btid))
1798  {
1799  cls_btname = cls_rep->indexes[i].btname;
1800  break;
1801  }
1802  }
1803 
1804  if (cls_btname == NULL)
1805  {
1806  assert (false);
1808  return NULL;
1809  }
1810 
1811  /* find the inherited index in the subclass */
1812  for (i = 0; i < subcls_rep->n_indexes; i++)
1813  {
1814  if (strcasecmp (cls_btname, subcls_rep->indexes[i].btname) == 0)
1815  {
1816  subcls_btid = &subcls_rep->indexes[i].btid;
1817  break;
1818  }
1819  }
1820 
1821  if (subcls_btid == NULL)
1822  {
1823  assert (false);
1825  return NULL;
1826  }
1827 
1828  for (i = 0, btstats = subcls_attr->bt_stats; i < subcls_attr->n_btstats; i++, btstats++)
1829  {
1830  if (BTID_IS_EQUAL (subcls_btid, &btstats->btid))
1831  {
1832  return btstats;
1833  }
1834  }
1835 
1836  assert (false);
1838  return NULL;
1839 }
DB_TIME time
Definition: dbtype_def.h:1056
#define OR_BTID_ALIGNED_SIZE
int ci_tot_pages
OID * oid_Root_class_oid
Definition: oid.c:73
#define NO_ERROR
Definition: error_code.h:46
CLS_INFO * catalog_get_class_info(THREAD_ENTRY *thread_p, OID *class_id_p, CATALOG_ACCESS_INFO *catalog_access_info_p)
short sh
Definition: dbtype_def.h:1050
MVCC_SNAPSHOT * logtb_get_mvcc_snapshot(THREAD_ENTRY *thread_p)
DB_TIMESTAMP timestamp
Definition: dbtype_def.h:766
int btree_get_stats(THREAD_ENTRY *thread_p, BTREE_STATS *stat_info_p, bool with_fullscan)
Definition: btree.c:6959
DB_TYPE
Definition: dbtype_def.h:670
#define ER_FAILED
Definition: error_code.h:47
int n_btstats
Definition: statistics.h:80
int partition_get_partition_oids(THREAD_ENTRY *thread_p, const OID *class_oid, OID **partition_oids, int *count)
Definition: partition.c:3380
int catalog_add_class_info(THREAD_ENTRY *thread_p, OID *class_id_p, CLS_INFO *class_info_p, CATALOG_ACCESS_INFO *catalog_access_info_p)
struct tp_domain * setdomain
Definition: object_domain.h:82
static int stats_update_partitioned_statistics(THREAD_ENTRY *thread_p, OID *class_oid, OID *partitions, int count, bool with_fullscan)
DB_DATETIME datetime
Definition: dbtype_def.h:1060
int xbtree_get_unique_pk(THREAD_ENTRY *thread_p, BTID *btid)
Definition: btree.c:6129
#define ASSERT_ERROR_AND_SET(error_code)
#define ER_UPDATE_STAT_CANNOT_GET_LOCK
Definition: error_code.h:1497
#define assert_release(e)
Definition: error_manager.h:96
unsigned int ci_time_stamp
int pkeys_size
Definition: statistics.h:66
int lock_object(THREAD_ENTRY *thread_p, const OID *oid, const OID *class_oid, LOCK lock, int cond_flag)
TP_DOMAIN * key_type
Definition: statistics.h:65
#define OID_SET_NULL(oidp)
Definition: oid.h:85
#define NULL_SLOTID
char * data
#define CAST_STRLEN
Definition: porting.h:470
#define BTID_IS_EQUAL(b1, b2)
int er_errid(void)
int or_packed_domain_size(struct tp_domain *domain, int include_classoids)
int heap_scancache_end(THREAD_ENTRY *thread_p, HEAP_SCANCACHE *scan_cache)
Definition: heap_file.c:7195
#define CATALOG_ACCESS_INFO_INITIALIZER
#define ER_LOG_FINISHED_TO_UPDATE_STATISTICS
Definition: error_code.h:1415
int catalog_start_access_with_dir_oid(THREAD_ENTRY *thread_p, CATALOG_ACCESS_INFO *catalog_access_info, LOCK lock_mode)
int ci_tot_objects
#define VFID_ISNULL(vfid_ptr)
Definition: file_manager.h:72
void THREAD_ENTRY
#define NULL_PAGEID
int heap_scancache_start(THREAD_ENTRY *thread_p, HEAP_SCANCACHE *scan_cache, const HFID *hfid, const OID *class_oid, int cache_last_fix_page, int is_indexscan, MVCC_SNAPSHOT *mvcc_snapshot)
Definition: heap_file.c:6833
DB_BIGINT bigint
Definition: dbtype_def.h:1051
int boot_find_root_heap(HFID *root_hfid_p)
Definition: boot_sr.c:325
#define RECDES_INITIALIZER
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
int catalog_end_access_with_dir_oid(THREAD_ENTRY *thread_p, CATALOG_ACCESS_INFO *catalog_access_info, int error)
DB_TIMESTAMP utime
Definition: dbtype_def.h:1058
#define assert(x)
int * pkeys
Definition: statistics.h:67
BTREE_STATS * bt_stats
int32_t fileid
Definition: dbtype_def.h:886
int file_get_num_user_pages(THREAD_ENTRY *thread_p, const VFID *vfid, int *n_user_pages_out)
int xstats_update_all_statistics(THREAD_ENTRY *thread_p, bool with_fullscan)
#define ER_GENERIC_ERROR
Definition: error_code.h:49
int tp_domain_size(const TP_DOMAIN *domain)
DB_DATETIME datetime
Definition: dbtype_def.h:783
#define BTREE_STATS_PKEYS_NUM
Definition: statistics.h:41
void lock_unlock_object(THREAD_ENTRY *thread_p, const OID *oid, const OID *class_oid, LOCK lock, bool force)
unsigned int stats_get_time_stamp(void)
#define heap_classrepr_free_and_init(class_repr, idxp)
Definition: heap_file.h:91
int catalog_add_representation(THREAD_ENTRY *thread_p, OID *class_id_p, REPR_ID repr_id, DISK_REPR *disk_repr_p, OID *rep_dir_p, CATALOG_ACCESS_INFO *catalog_access_info_p)
VFID vfid
#define TP_DOMAIN_TYPE(dom)
static void cleanup(int signo)
Definition: broker.c:717
#define NULL
Definition: freelistheap.h:34
struct disk_attribute * variable
DB_DATE date
Definition: dbtype_def.h:1057
VFID vfid
DB_TIMESTAMPTZ timestamptz
Definition: dbtype_def.h:1059
#define err(fd,...)
Definition: porting.h:431
int heap_estimate_num_objects(THREAD_ENTRY *thread_p, const HFID *hfid)
Definition: heap_file.c:9060
#define db_private_free_and_init(thrd, ptr)
Definition: memory_alloc.h:141
#define OR_PUT_BTID(ptr, btid)
int catalog_get_dir_oid_from_cache(THREAD_ENTRY *thread_p, const OID *class_id_p, OID *dir_oid_p)
#define db_private_free(thrd, ptr)
Definition: memory_alloc.h:229
#define db_private_alloc(thrd, size)
Definition: memory_alloc.h:227
struct disk_attribute * fixed
OR_CLASSREP * heap_classrepr_get(THREAD_ENTRY *thread_p, const OID *class_oid, RECDES *class_recdes, REPR_ID reprid, int *idx_incache)
Definition: heap_file.c:2299
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
#define NULL_REPRID
static void error(const char *msg)
Definition: gencat.c:331
char * xstats_get_statistics_from_server(THREAD_ENTRY *thread_p, OID *class_id_p, unsigned int time_stamp, int *length_p)
#define ER_INTERRUPTED
Definition: error_code.h:51
int xstats_update_statistics(THREAD_ENTRY *thread_p, OID *class_id_p, bool with_fullscan)
#define HFID_IS_NULL(hfid)
int catalog_get_last_representation_id(THREAD_ENTRY *thread_p, OID *class_oid_p, REPR_ID *repr_id_p)
char * or_class_name(RECDES *record)
#define ER_SP_UNKNOWN_SLOTID
Definition: error_code.h:99
#define ARG_FILE_LINE
Definition: error_manager.h:44
unsigned int time_stamp
Definition: statistics.h:88
static const bool COPY
unsigned int DB_TIME
Definition: dbtype_def.h:754
BTREE_STATS * bt_stats
Definition: statistics.h:81
unsigned int DB_DATE
Definition: dbtype_def.h:771
#define SQUARE(n)
Definition: statistics_sr.c:42
#define free_and_init(ptr)
Definition: memory_alloc.h:147
#define strlen(s1)
Definition: intl_support.c:43
char * or_pack_domain(char *ptr, struct tp_domain *domain, int include_classoids, int is_null)
unsigned int date
Definition: dbtype_def.h:776
bool prm_get_bool_value(PARAM_ID prm_id)
#define OR_PUT_INT(ptr, val)
void er_clear(void)
int REPR_ID
int i
Definition: dynamic_load.c:954
int has_function
Definition: statistics.h:64
int heap_num_pages
Definition: statistics.h:90
int heap_num_objects
Definition: statistics.h:89
#define ER_LOG_STARTED_TO_UPDATE_STATISTICS
Definition: error_code.h:1414
#define BTID_IS_NULL(btid)
#define catalog_free_class_info_and_init(class_info_p)
short volid
Definition: dbtype_def.h:887
#define OID_ISNULL(oidp)
Definition: oid.h:81
DB_TIMESTAMP DB_UTIME
Definition: dbtype_def.h:761
SCAN_CODE heap_next(THREAD_ENTRY *thread_p, const HFID *hfid, OID *class_oid, OID *next_oid, RECDES *recdes, HEAP_SCANCACHE *scan_cache, int ispeeking)
Definition: heap_file.c:18622
CLASS_ID_LIST * next
Definition: statistics_sr.c:50
int heap_get_class_name(THREAD_ENTRY *thread_p, const OID *class_oid, char **class_name)
Definition: heap_file.c:9328
double amount
Definition: dbtype_def.h:831
HFID ci_hfid
float f
Definition: dbtype_def.h:1052
ATTR_STATS * attr_stats
Definition: statistics.h:92
#define catalog_free_representation_and_init(repr_p)
double d
Definition: dbtype_def.h:1053
DB_MONETARY money
Definition: dbtype_def.h:1062
unsigned int time
Definition: dbtype_def.h:777
const BTREE_STATS * stats_find_inherited_index_stats(OR_CLASSREP *cls_rep, OR_CLASSREP *subcls_rep, DISK_ATTR *subcls_attr, BTID *cls_btid)
DB_TYPE type
Definition: statistics.h:79
DB_DATETIMETZ datetimetz
Definition: dbtype_def.h:1061
DISK_REPR * catalog_get_representation(THREAD_ENTRY *thread_p, OID *class_id_p, REPR_ID repr_id, CATALOG_ACCESS_INFO *catalog_access_info_p)