CUBRID Engine  latest
query_analytic.cpp
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 // query_analytic - implementation of analytic query execution
21 //
22 
23 #include "query_analytic.hpp"
24 
25 #include "dbtype.h"
26 #include "fetch.h"
27 #include "list_file.h"
28 #include "object_domain.h"
29 #include "object_primitive.h"
30 #include "object_representation.h"
31 #include "query_opfunc.h"
32 #include "xasl.h" // QPROC_IS_INTERPOLATION_FUNC
33 #include "xasl_analytic.hpp"
34 
35 #include <cmath>
36 
38  QFILE_LIST_SCAN_ID *scan_id);
39 
40 /*
41  * qdata_initialize_analytic_func () -
42  * return: NO_ERROR, or ER_code
43  * func_p(in): Analytic expression node
44  * query_id(in): Associated query id
45  *
46  */
47 int
48 qdata_initialize_analytic_func (cubthread::entry *thread_p, ANALYTIC_TYPE *func_p, QUERY_ID query_id)
49 {
50  func_p->curr_cnt = 0;
52  != NO_ERROR)
53  {
54  return ER_FAILED;
55  }
56 
57  if (func_p->function == PT_COUNT_STAR || func_p->function == PT_COUNT || func_p->function == PT_ROW_NUMBER
58  || func_p->function == PT_RANK || func_p->function == PT_DENSE_RANK)
59  {
60  db_make_int (func_p->value, 0);
61  }
62 
63  db_make_null (&func_p->part_value);
64 
65  /* create temporary list file to handle distincts */
66  if (func_p->option == Q_DISTINCT)
67  {
69  QFILE_LIST_ID *list_id_p;
70 
71  type_list.type_cnt = 1;
72  type_list.domp = (TP_DOMAIN **) db_private_alloc (thread_p, sizeof (TP_DOMAIN *));
73  if (type_list.domp == NULL)
74  {
75  return ER_FAILED;
76  }
77  type_list.domp[0] = func_p->operand.domain;
78 
79  list_id_p = qfile_open_list (thread_p, &type_list, NULL, query_id, QFILE_FLAG_DISTINCT);
80  if (list_id_p == NULL)
81  {
82  db_private_free_and_init (thread_p, type_list.domp);
83  return ER_FAILED;
84  }
85 
86  db_private_free_and_init (thread_p, type_list.domp);
87 
88  if (qfile_copy_list_id (func_p->list_id, list_id_p, true) != NO_ERROR)
89  {
90  qfile_free_list_id (list_id_p);
91  return ER_FAILED;
92  }
93 
94  qfile_free_list_id (list_id_p);
95  }
96 
97  return NO_ERROR;
98 }
99 
100 /*
101  * qdata_evaluate_analytic_func () -
102  * return: NO_ERROR, or ER_code
103  * func_p(in): Analytic expression node
104  * vd(in): Value descriptor
105  *
106  */
107 int
109 {
110  DB_VALUE dbval, sqr_val;
111  DB_VALUE *opr_dbval_p = NULL;
112  PR_TYPE *pr_type_p;
113  OR_BUF buf;
114  char *disk_repr_p = NULL;
115  int dbval_size;
116  int copy_opr;
117  TP_DOMAIN *tmp_domain_p = NULL;
118  DB_TYPE dbval_type;
119  int error = NO_ERROR;
120  TP_DOMAIN_STATUS dom_status;
121  int coll_id;
122  ANALYTIC_PERCENTILE_FUNCTION_INFO *percentile_info_p = NULL;
123  DB_VALUE *peek_value_p = NULL;
124 
125  db_make_null (&dbval);
126  db_make_null (&sqr_val);
127 
128  /* fetch operand value, analytic regulator variable should only contain constants */
129  if (fetch_copy_dbval (thread_p, &func_p->operand, val_desc_p, NULL, NULL, NULL, &dbval) != NO_ERROR)
130  {
131  return ER_FAILED;
132  }
133 
135  && !DB_IS_NULL (&dbval))
136  {
137  /* set function default domain when late binding */
138  switch (func_p->function)
139  {
140  case PT_COUNT:
141  case PT_COUNT_STAR:
143  break;
144 
145  case PT_AVG:
146  case PT_STDDEV:
147  case PT_STDDEV_POP:
148  case PT_STDDEV_SAMP:
149  case PT_VARIANCE:
150  case PT_VAR_POP:
151  case PT_VAR_SAMP:
153  break;
154 
155  case PT_SUM:
156  if (TP_IS_NUMERIC_TYPE (DB_VALUE_TYPE (&dbval)))
157  {
158  func_p->domain = tp_domain_resolve_value (&dbval, NULL);
159  }
160  else
161  {
163  }
164  break;
165 
166  default:
167  func_p->domain = tp_domain_resolve_value (&dbval, NULL);
168  break;
169  }
170 
171  if (func_p->domain == NULL)
172  {
173  error = ER_FAILED;
174  goto exit;
175  }
176 
177  /* coerce operand */
178  if (tp_value_coerce (&dbval, &dbval, func_p->domain) != DOMAIN_COMPATIBLE)
179  {
180  error = ER_FAILED;
181  goto exit;
182  }
183 
184  func_p->opr_dbtype = TP_DOMAIN_TYPE (func_p->domain);
186  }
187 
188  if (DB_IS_NULL (&dbval) && func_p->function != PT_ROW_NUMBER && func_p->function != PT_FIRST_VALUE
189  && func_p->function != PT_LAST_VALUE && func_p->function != PT_NTH_VALUE && func_p->function != PT_RANK
190  && func_p->function != PT_DENSE_RANK && func_p->function != PT_LEAD && func_p->function != PT_LAG
191  && !QPROC_IS_INTERPOLATION_FUNC (func_p))
192  {
193  if (func_p->function == PT_COUNT || func_p->function == PT_COUNT_STAR)
194  {
195  func_p->curr_cnt++;
196  }
197 
198  if (func_p->function == PT_NTILE)
199  {
200  func_p->info.ntile.is_null = true;
201  func_p->info.ntile.bucket_count = 0;
202  }
203  goto exit;
204  }
205 
206  if (func_p->option == Q_DISTINCT)
207  {
208  /* handle distincts by adding to the temp list file */
209  dbval_type = DB_VALUE_DOMAIN_TYPE (&dbval);
210  pr_type_p = pr_type_from_id (dbval_type);
211 
212  if (pr_type_p == NULL)
213  {
214  error = ER_FAILED;
215  goto exit;
216  }
217 
218  dbval_size = pr_data_writeval_disk_size (&dbval);
219  if (dbval_size > 0 && (disk_repr_p = (char *) db_private_alloc (thread_p, dbval_size)) != NULL)
220  {
221  OR_BUF_INIT (buf, disk_repr_p, dbval_size);
222  error = pr_type_p->data_writeval (&buf, &dbval);
223  if (error != NO_ERROR)
224  {
225  /* ER_TF_BUFFER_OVERFLOW means that val_size or packing is bad. */
226  assert (error != ER_TF_BUFFER_OVERFLOW);
227 
228  db_private_free_and_init (thread_p, disk_repr_p);
229  error = ER_FAILED;
230  goto exit;
231  }
232  }
233  else
234  {
235  error = ER_FAILED;
236  goto exit;
237  }
238 
239  if (qfile_add_item_to_list (thread_p, disk_repr_p, dbval_size, func_p->list_id) != NO_ERROR)
240  {
241  db_private_free_and_init (thread_p, disk_repr_p);
242  error = ER_FAILED;
243  goto exit;
244  }
245  db_private_free_and_init (thread_p, disk_repr_p);
246 
247  /* interpolation funcs need to check domain compatibility in the following code */
248  if (!QPROC_IS_INTERPOLATION_FUNC (func_p))
249  {
250  goto exit;
251  }
252  }
253 
254  copy_opr = false;
255  coll_id = func_p->domain->collation_id;
256  switch (func_p->function)
257  {
258  case PT_CUME_DIST:
259  case PT_PERCENT_RANK:
260  /* these functions do not execute here, just in case */
261  pr_clear_value (func_p->value);
262  break;
263 
264  case PT_NTILE:
265  /* output value is not required now */
266  db_make_null (func_p->value);
267 
268  if (func_p->curr_cnt < 1)
269  {
270  /* the operand is the number of buckets and should be constant within the window; we can extract it now for
271  * later use */
272  dom_status = tp_value_coerce (&dbval, &dbval, &tp_Double_domain);
273  if (dom_status != DOMAIN_COMPATIBLE)
274  {
275  error = tp_domain_status_er_set (dom_status, ARG_FILE_LINE, &dbval, &tp_Double_domain);
276  assert_release (error != NO_ERROR);
277 
278  goto exit;
279  }
280 
281  int ntile_bucket = (int) floor (db_get_double (&dbval));
282 
283  /* boundary check */
284  if (ntile_bucket < 1 || ntile_bucket > DB_INT32_MAX)
285  {
288  goto exit;
289  }
290 
291  /* we're sure the operand is not null */
292  func_p->info.ntile.is_null = false;
293  func_p->info.ntile.bucket_count = ntile_bucket;
294  }
295  break;
296 
297  case PT_FIRST_VALUE:
298  if ((func_p->ignore_nulls && DB_IS_NULL (func_p->value)) || (func_p->curr_cnt < 1))
299  {
300  /* copy value if it's the first value OR if we're ignoring NULLs and we've only encountered NULL values so
301  * far */
302  (void) pr_clear_value (func_p->value);
303  pr_clone_value (&dbval, func_p->value);
304  }
305  break;
306 
307  case PT_LAST_VALUE:
308  if (!func_p->ignore_nulls || !DB_IS_NULL (&dbval))
309  {
310  (void) pr_clear_value (func_p->value);
311  pr_clone_value (&dbval, func_p->value);
312  }
313  break;
314 
315  case PT_LEAD:
316  case PT_LAG:
317  case PT_NTH_VALUE:
318  /* just copy */
319  (void) pr_clear_value (func_p->value);
320  pr_clone_value (&dbval, func_p->value);
321  break;
322 
323  case PT_MIN:
324  opr_dbval_p = &dbval;
325  if ((func_p->curr_cnt < 1 || DB_IS_NULL (func_p->value))
326  || func_p->domain->type->cmpval (func_p->value, &dbval, 1, 1, NULL, coll_id) > 0)
327  {
328  copy_opr = true;
329  }
330  break;
331 
332  case PT_MAX:
333  opr_dbval_p = &dbval;
334  if ((func_p->curr_cnt < 1 || DB_IS_NULL (func_p->value))
335  || func_p->domain->type->cmpval (func_p->value, &dbval, 1, 1, NULL, coll_id) < 0)
336  {
337  copy_opr = true;
338  }
339  break;
340 
341  case PT_AVG:
342  case PT_SUM:
343  if (func_p->curr_cnt < 1)
344  {
345  opr_dbval_p = &dbval;
346  copy_opr = true;
347 
348  if (TP_IS_CHAR_TYPE (DB_VALUE_DOMAIN_TYPE (opr_dbval_p)))
349  {
350  /* char types default to double; coerce here so we don't mess up the accumulator when we copy the operand
351  */
352  if (tp_value_coerce (&dbval, &dbval, func_p->domain) != DOMAIN_COMPATIBLE)
353  {
354  error = ER_FAILED;
355  goto exit;
356  }
357  }
358 
359  /* this type setting is necessary, it ensures that for the case average handling, which is treated like sum
360  * until final iteration, starts with the initial data type */
363  {
364  error = ER_FAILED;
365  goto exit;
366  }
367  }
368  else
369  {
370  TP_DOMAIN *result_domain;
371  DB_TYPE type =
372  (func_p->function ==
373  PT_AVG) ? (DB_TYPE) func_p->value->domain.general_info.type : TP_DOMAIN_TYPE (func_p->domain);
374 
375  result_domain = ((type == DB_TYPE_NUMERIC) ? NULL : func_p->domain);
376  if (qdata_add_dbval (func_p->value, &dbval, func_p->value, result_domain) != NO_ERROR)
377  {
378  error = ER_FAILED;
379  goto exit;
380  }
381  copy_opr = false;
382  }
383  break;
384 
385  case PT_COUNT_STAR:
386  break;
387 
388  case PT_ROW_NUMBER:
389  db_make_int (func_p->out_value, func_p->curr_cnt + 1);
390  break;
391 
392  case PT_COUNT:
393  if (func_p->curr_cnt < 1)
394  {
395  db_make_int (func_p->value, 1);
396  }
397  else
398  {
399  db_make_int (func_p->value, db_get_int (func_p->value) + 1);
400  }
401  break;
402 
403  case PT_RANK:
404  if (func_p->curr_cnt < 1)
405  {
406  db_make_int (func_p->value, 1);
407  }
408  else
409  {
411  {
413  }
414  else
415  {
416  db_make_int (func_p->value, func_p->curr_cnt + 1);
417  }
418  }
419  break;
420 
421  case PT_DENSE_RANK:
422  if (func_p->curr_cnt < 1)
423  {
424  db_make_int (func_p->value, 1);
425  }
426  else
427  {
429  {
431  }
432  else
433  {
434  db_make_int (func_p->value, db_get_int (func_p->value) + 1);
435  }
436  }
437  break;
438 
439  case PT_STDDEV:
440  case PT_STDDEV_POP:
441  case PT_STDDEV_SAMP:
442  case PT_VARIANCE:
443  case PT_VAR_POP:
444  case PT_VAR_SAMP:
445  copy_opr = false;
446  tmp_domain_p = tp_domain_resolve_default (DB_TYPE_DOUBLE);
447 
448  if (tp_value_coerce (&dbval, &dbval, tmp_domain_p) != DOMAIN_COMPATIBLE)
449  {
450  error = ER_FAILED;
451  goto exit;
452  }
453 
454  if (func_p->curr_cnt < 1)
455  {
456  opr_dbval_p = &dbval;
457  /* func_p->value contains SUM(X) */
460  {
461  error = ER_FAILED;
462  goto exit;
463  }
464 
465  /* func_p->value contains SUM(X^2) */
468  {
469  error = ER_FAILED;
470  goto exit;
471  }
472 
473  /* calculate X^2 */
474  if (qdata_multiply_dbval (&dbval, &dbval, &sqr_val, tmp_domain_p) != NO_ERROR)
475  {
476  error = ER_FAILED;
477  goto exit;
478  }
479 
480  (void) pr_clear_value (func_p->value);
481  (void) pr_clear_value (func_p->value2);
482  dbval_type = DB_VALUE_DOMAIN_TYPE (func_p->value);
483  pr_type_p = pr_type_from_id (dbval_type);
484  if (pr_type_p == NULL)
485  {
486  error = ER_FAILED;
487  goto exit;
488  }
489 
490  pr_type_p->setval (func_p->value, &dbval, true);
491  pr_type_p->setval (func_p->value2, &sqr_val, true);
492  }
493  else
494  {
495  if (qdata_multiply_dbval (&dbval, &dbval, &sqr_val, tmp_domain_p) != NO_ERROR)
496  {
497  error = ER_FAILED;
498  goto exit;
499  }
500 
501  if (qdata_add_dbval (func_p->value, &dbval, func_p->value, tmp_domain_p) != NO_ERROR)
502  {
503  pr_clear_value (&sqr_val);
504  error = ER_FAILED;
505  goto exit;
506  }
507 
508  if (qdata_add_dbval (func_p->value2, &sqr_val, func_p->value2, tmp_domain_p) != NO_ERROR)
509  {
510  pr_clear_value (&sqr_val);
511  error = ER_FAILED;
512  goto exit;
513  }
514 
515  pr_clear_value (&sqr_val);
516  }
517  break;
518 
519  case PT_MEDIAN:
520  case PT_PERCENTILE_CONT:
521  case PT_PERCENTILE_DISC:
522  if (func_p->function == PT_PERCENTILE_CONT || func_p->function == PT_PERCENTILE_DISC)
523  {
524  percentile_info_p = &func_p->info.percentile;
525  }
526 
527  if (func_p->curr_cnt < 1)
528  {
529  if (func_p->function == PT_PERCENTILE_CONT || func_p->function == PT_PERCENTILE_DISC)
530  {
531  error =
532  fetch_peek_dbval (thread_p, percentile_info_p->percentile_reguvar, NULL, NULL, NULL, NULL,
533  &peek_value_p);
534  if (error != NO_ERROR)
535  {
536  assert (er_errid () != NO_ERROR);
537 
538  goto exit;
539  }
540 
541  if ((peek_value_p == NULL) || (DB_VALUE_TYPE (peek_value_p) != DB_TYPE_DOUBLE))
542  {
545  goto exit;
546  }
547 
548  percentile_info_p->cur_group_percentile = db_get_double (peek_value_p);
549  if ((percentile_info_p->cur_group_percentile < 0) || (percentile_info_p->cur_group_percentile > 1))
550  {
552  percentile_info_p->cur_group_percentile);
554  goto exit;
555  }
556  }
557 
558  if (func_p->is_first_exec_time)
559  {
560  func_p->is_first_exec_time = false;
561  /* determine domain based on first value */
562  switch (func_p->opr_dbtype)
563  {
564  case DB_TYPE_SHORT:
565  case DB_TYPE_INTEGER:
566  case DB_TYPE_BIGINT:
567  case DB_TYPE_FLOAT:
568  case DB_TYPE_DOUBLE:
569  case DB_TYPE_MONETARY:
570  case DB_TYPE_NUMERIC:
571  if (TP_DOMAIN_TYPE (func_p->domain) == DB_TYPE_VARIABLE)
572  {
573  if (func_p->is_const_operand || func_p->function == PT_PERCENTILE_DISC)
574  {
575  /* percentile_disc returns the same type as operand while median and percentile_cont return
576  * double */
577  func_p->domain = tp_domain_resolve_value (&dbval, NULL);
578  if (func_p->domain == NULL)
579  {
580  error = er_errid ();
581  assert (error != NO_ERROR);
582 
583  return error;
584  }
585  }
586  else
587  {
589  }
590  }
591  break;
592 
593  case DB_TYPE_DATE:
594  if (TP_DOMAIN_TYPE (func_p->domain) == DB_TYPE_VARIABLE)
595  {
597  }
598  break;
599 
600  case DB_TYPE_DATETIME:
601  if (TP_DOMAIN_TYPE (func_p->domain) == DB_TYPE_VARIABLE)
602  {
604  }
605  break;
606 
607  case DB_TYPE_DATETIMETZ:
608  if (TP_DOMAIN_TYPE (func_p->domain) == DB_TYPE_VARIABLE)
609  {
611  }
612  break;
613 
614  case DB_TYPE_DATETIMELTZ:
615  if (TP_DOMAIN_TYPE (func_p->domain) == DB_TYPE_VARIABLE)
616  {
618  }
619  break;
620 
621  case DB_TYPE_TIMESTAMP:
622  if (TP_DOMAIN_TYPE (func_p->domain) == DB_TYPE_VARIABLE)
623  {
625  }
626  break;
627 
628  case DB_TYPE_TIMESTAMPTZ:
629  if (TP_DOMAIN_TYPE (func_p->domain) == DB_TYPE_VARIABLE)
630  {
632  }
633  break;
634 
636  if (TP_DOMAIN_TYPE (func_p->domain) == DB_TYPE_VARIABLE)
637  {
639  }
640  break;
641 
642  case DB_TYPE_TIME:
643  if (TP_DOMAIN_TYPE (func_p->domain) == DB_TYPE_VARIABLE)
644  {
646  }
647  break;
648 
649  default:
650  /* try to cast dbval to double, datetime then time */
651  tmp_domain_p = tp_domain_resolve_default (DB_TYPE_DOUBLE);
652 
653  dom_status = tp_value_cast (&dbval, &dbval, tmp_domain_p, false);
654  if (dom_status != DOMAIN_COMPATIBLE)
655  {
656  /* try datetime */
658 
659  dom_status = tp_value_cast (&dbval, &dbval, tmp_domain_p, false);
660  }
661 
662  /* try time */
663  if (dom_status != DOMAIN_COMPATIBLE)
664  {
665  tmp_domain_p = tp_domain_resolve_default (DB_TYPE_TIME);
666 
667  dom_status = tp_value_cast (&dbval, &dbval, tmp_domain_p, false);
668  }
669 
670  if (dom_status != DOMAIN_COMPATIBLE)
671  {
674  "DOUBLE, DATETIME, TIME");
675  goto exit;
676  }
677 
678  /* update domain */
679  func_p->domain = tmp_domain_p;
680  }
681  }
682  }
683 
684  /* percentile value check */
685  if (func_p->function == PT_PERCENTILE_CONT || func_p->function == PT_PERCENTILE_DISC)
686  {
687  error =
688  fetch_peek_dbval (thread_p, percentile_info_p->percentile_reguvar, NULL, NULL, NULL, NULL, &peek_value_p);
689  if (error != NO_ERROR)
690  {
691  assert (er_errid () != NO_ERROR);
692 
693  goto exit;
694  }
695 
696  if ((peek_value_p == NULL) || (DB_VALUE_TYPE (peek_value_p) != DB_TYPE_DOUBLE)
697  || (db_get_double (peek_value_p) != func_p->info.percentile.cur_group_percentile))
698  {
701  goto exit;
702  }
703  }
704 
705  /* copy value */
706  pr_clear_value (func_p->value);
707  error = db_value_coerce (&dbval, func_p->value, func_p->domain);
708  if (error != NO_ERROR)
709  {
710  goto exit;
711  }
712  break;
713 
714  default:
717  goto exit;
718  }
719 
720  if (copy_opr)
721  {
722  /* copy resultant operand value to analytic node */
723  (void) pr_clear_value (func_p->value);
724  dbval_type = DB_VALUE_DOMAIN_TYPE (func_p->value);
725  pr_type_p = pr_type_from_id (dbval_type);
726  if (pr_type_p == NULL)
727  {
728  error = ER_FAILED;
729  goto exit;
730  }
731 
732  pr_type_p->setval (func_p->value, opr_dbval_p, true);
733  }
734 
735  func_p->curr_cnt++;
736 
737 exit:
738  pr_clear_value (&dbval);
739 
740  return error;
741 }
742 
743 /*
744  * qdata_finalize_analytic_func () -
745  * return: NO_ERROR, or ER_code
746  * func_p(in): Analytic expression node
747  * is_same_group(in): Don't deallocate list file
748  *
749  */
750 int
751 qdata_finalize_analytic_func (cubthread::entry *thread_p, ANALYTIC_TYPE *func_p, bool is_same_group)
752 {
753  DB_VALUE dbval;
754  QFILE_LIST_ID *list_id_p;
755  char *tuple_p;
756  PR_TYPE *pr_type_p;
757  OR_BUF buf;
758  QFILE_LIST_SCAN_ID scan_id;
759  SCAN_CODE scan_code;
760  DB_VALUE xavgval, xavg_1val, x2avgval;
761  DB_VALUE xavg2val, varval, sqr_val, dval;
762  double dtmp;
763  QFILE_TUPLE_RECORD tuple_record = { NULL, 0 };
764  TP_DOMAIN *tmp_domain_ptr = NULL;
765  int err = NO_ERROR;
766 
767  db_make_null (&sqr_val);
768  db_make_null (&dbval);
769  db_make_null (&xavgval);
770  db_make_null (&xavg_1val);
771  db_make_null (&x2avgval);
772  db_make_null (&xavg2val);
773  db_make_null (&varval);
774  db_make_null (&dval);
775 
776  if (func_p->function == PT_VARIANCE || func_p->function == PT_VAR_POP || func_p->function == PT_VAR_SAMP
777  || func_p->function == PT_STDDEV || func_p->function == PT_STDDEV_POP || func_p->function == PT_STDDEV_SAMP)
778  {
779  tmp_domain_ptr = tp_domain_resolve_default (DB_TYPE_DOUBLE);
780  }
781 
782  /* set count-star aggregate values */
783  if (func_p->function == PT_COUNT_STAR)
784  {
785  db_make_int (func_p->value, func_p->curr_cnt);
786  }
787 
788  /* process list file for distinct */
789  if (func_p->option == Q_DISTINCT)
790  {
791  assert (func_p->list_id->sort_list != NULL);
792 
793  list_id_p = qfile_sort_list (thread_p, func_p->list_id, NULL, Q_DISTINCT, false);
794 
795  /* release the resource to prevent resource leak */
796  if (func_p->list_id != list_id_p)
797  {
798  qfile_close_list (thread_p, func_p->list_id);
799  qfile_destroy_list (thread_p, func_p->list_id);
800  }
801 
802  if (!list_id_p)
803  {
804  return ER_FAILED;
805  }
806 
807  func_p->list_id = list_id_p;
808 
809  if (func_p->function == PT_COUNT)
810  {
811  db_make_int (func_p->value, list_id_p->tuple_cnt);
812  }
813  else
814  {
815  pr_type_p = list_id_p->type_list.domp[0]->type;
816 
817  /* scan list file, accumulating total for sum/avg */
818  if (qfile_open_list_scan (list_id_p, &scan_id) != NO_ERROR)
819  {
820  qfile_close_list (thread_p, list_id_p);
821  qfile_destroy_list (thread_p, list_id_p);
822  return ER_FAILED;
823  }
824 
825  (void) pr_clear_value (func_p->value);
826 
827  db_make_null (func_p->value);
828 
829  /* median and percentile funcs don't need to read all rows */
830  if (list_id_p->tuple_cnt > 0 && QPROC_IS_INTERPOLATION_FUNC (func_p))
831  {
832  err = qdata_analytic_interpolation (thread_p, func_p, &scan_id);
833  if (err != NO_ERROR)
834  {
835  qfile_close_scan (thread_p, &scan_id);
836  qfile_close_list (thread_p, list_id_p);
837  qfile_destroy_list (thread_p, list_id_p);
838 
839  goto error;
840  }
841  }
842  else
843  {
844  while (true)
845  {
846  scan_code = qfile_scan_list_next (thread_p, &scan_id, &tuple_record, PEEK);
847  if (scan_code != S_SUCCESS)
848  {
849  break;
850  }
851 
852  tuple_p = ((char *) tuple_record.tpl + QFILE_TUPLE_LENGTH_SIZE);
853  if (QFILE_GET_TUPLE_VALUE_FLAG (tuple_p) == V_UNBOUND)
854  {
855  continue;
856  }
857 
858  or_init (&buf, (char *) tuple_p + QFILE_TUPLE_VALUE_HEADER_SIZE,
859  QFILE_GET_TUPLE_VALUE_LENGTH (tuple_p));
860  if (pr_type_p->data_readval (&buf, &dbval, list_id_p->type_list.domp[0], -1, true, NULL, 0) !=
861  NO_ERROR)
862  {
863  qfile_close_scan (thread_p, &scan_id);
864  qfile_close_list (thread_p, list_id_p);
865  qfile_destroy_list (thread_p, list_id_p);
866  return ER_FAILED;
867  }
868 
869  if (func_p->function == PT_VARIANCE || func_p->function == PT_VAR_POP
870  || func_p->function == PT_VAR_SAMP || func_p->function == PT_STDDEV
871  || func_p->function == PT_STDDEV_POP || func_p->function == PT_STDDEV_SAMP)
872  {
873  if (tp_value_coerce (&dbval, &dbval, tmp_domain_ptr) != DOMAIN_COMPATIBLE)
874  {
875  (void) pr_clear_value (&dbval);
876  qfile_close_scan (thread_p, &scan_id);
877  qfile_close_list (thread_p, list_id_p);
878  qfile_destroy_list (thread_p, list_id_p);
879  return ER_FAILED;
880  }
881  }
882 
883  if (DB_IS_NULL (func_p->value))
884  {
885  /* first iteration: can't add to a null agg_ptr->value */
886  PR_TYPE *tmp_pr_type;
887  DB_TYPE dbval_type = DB_VALUE_DOMAIN_TYPE (&dbval);
888 
889  tmp_pr_type = pr_type_from_id (dbval_type);
890  if (tmp_pr_type == NULL)
891  {
892  (void) pr_clear_value (&dbval);
893  qfile_close_scan (thread_p, &scan_id);
894  qfile_close_list (thread_p, list_id_p);
895  qfile_destroy_list (thread_p, list_id_p);
896  return ER_FAILED;
897  }
898 
899  if (func_p->function == PT_STDDEV || func_p->function == PT_STDDEV_POP
900  || func_p->function == PT_STDDEV_SAMP || func_p->function == PT_VARIANCE
901  || func_p->function == PT_VAR_POP || func_p->function == PT_VAR_SAMP)
902  {
903  if (qdata_multiply_dbval (&dbval, &dbval, &sqr_val, tmp_domain_ptr) != NO_ERROR)
904  {
905  (void) pr_clear_value (&dbval);
906  qfile_close_scan (thread_p, &scan_id);
907  qfile_close_list (thread_p, list_id_p);
908  qfile_destroy_list (thread_p, list_id_p);
909  return ER_FAILED;
910  }
911 
912  tmp_pr_type->setval (func_p->value2, &sqr_val, true);
913  }
914 
915  tmp_pr_type->setval (func_p->value, &dbval, true);
916  }
917  else
918  {
919  TP_DOMAIN *domain_ptr;
920 
921  if (func_p->function == PT_STDDEV || func_p->function == PT_STDDEV_POP
922  || func_p->function == PT_STDDEV_SAMP || func_p->function == PT_VARIANCE
923  || func_p->function == PT_VAR_POP || func_p->function == PT_VAR_SAMP)
924  {
925  if (qdata_multiply_dbval (&dbval, &dbval, &sqr_val, tmp_domain_ptr) != NO_ERROR)
926  {
927  (void) pr_clear_value (&dbval);
928  qfile_close_scan (thread_p, &scan_id);
929  qfile_close_list (thread_p, list_id_p);
930  qfile_destroy_list (thread_p, list_id_p);
931  return ER_FAILED;
932  }
933 
934  if (qdata_add_dbval (func_p->value2, &sqr_val, func_p->value2, tmp_domain_ptr) != NO_ERROR)
935  {
936  (void) pr_clear_value (&dbval);
937  pr_clear_value (&sqr_val);
938  qfile_close_scan (thread_p, &scan_id);
939  qfile_close_list (thread_p, list_id_p);
940  qfile_destroy_list (thread_p, list_id_p);
941  return ER_FAILED;
942  }
943  }
944 
945  domain_ptr = tmp_domain_ptr != NULL ? tmp_domain_ptr : func_p->domain;
946  if ((func_p->function == PT_AVG) && (dbval.domain.general_info.type == DB_TYPE_NUMERIC))
947  {
948  domain_ptr = NULL;
949  }
950 
951  if (qdata_add_dbval (func_p->value, &dbval, func_p->value, domain_ptr) != NO_ERROR)
952  {
953  (void) pr_clear_value (&dbval);
954  qfile_close_scan (thread_p, &scan_id);
955  qfile_close_list (thread_p, list_id_p);
956  qfile_destroy_list (thread_p, list_id_p);
957  return ER_FAILED;
958  }
959  }
960 
961  (void) pr_clear_value (&dbval);
962  } /* while (true) */
963  }
964 
965  qfile_close_scan (thread_p, &scan_id);
966  func_p->curr_cnt = list_id_p->tuple_cnt;
967  }
968  }
969 
970  if (is_same_group)
971  {
972  /* this is the end of a partition; save accumulator */
973  qdata_copy_db_value (&func_p->part_value, func_p->value);
974  }
975 
976  /* compute averages */
977  if (func_p->curr_cnt > 0
978  && (func_p->function == PT_AVG || func_p->function == PT_STDDEV || func_p->function == PT_STDDEV_POP
979  || func_p->function == PT_STDDEV_SAMP || func_p->function == PT_VARIANCE || func_p->function == PT_VAR_POP
980  || func_p->function == PT_VAR_SAMP))
981  {
982  TP_DOMAIN *double_domain_ptr;
983 
984  double_domain_ptr = tp_domain_resolve_default (DB_TYPE_DOUBLE);
985 
986  /* compute AVG(X) = SUM(X)/COUNT(X) */
987  db_make_double (&dbval, func_p->curr_cnt);
988  if (qdata_divide_dbval (func_p->value, &dbval, &xavgval, double_domain_ptr) != NO_ERROR)
989  {
990  goto error;
991  }
992 
993  if (func_p->function == PT_AVG)
994  {
995  (void) pr_clear_value (func_p->value);
996  if (tp_value_coerce (&xavgval, func_p->value, double_domain_ptr) != DOMAIN_COMPATIBLE)
997  {
998  goto error;
999  }
1000 
1001  goto exit;
1002  }
1003 
1004  if (func_p->function == PT_STDDEV_SAMP || func_p->function == PT_VAR_SAMP)
1005  {
1006  /* compute SUM(X^2) / (n-1) */
1007  if (func_p->curr_cnt > 1)
1008  {
1009  db_make_double (&dbval, func_p->curr_cnt - 1);
1010  }
1011  else
1012  {
1013  /* when not enough samples, return NULL */
1014  (void) pr_clear_value (func_p->value);
1015  db_make_null (func_p->value);
1016  goto exit;
1017  }
1018  }
1019  else
1020  {
1021  assert (func_p->function == PT_STDDEV || func_p->function == PT_STDDEV_POP || func_p->function == PT_VARIANCE
1022  || func_p->function == PT_VAR_POP);
1023  /* compute SUM(X^2) / n */
1024  db_make_double (&dbval, func_p->curr_cnt);
1025  }
1026 
1027  if (qdata_divide_dbval (func_p->value2, &dbval, &x2avgval, double_domain_ptr) != NO_ERROR)
1028  {
1029  goto error;
1030  }
1031 
1032  /* compute {SUM(X) / (n)} OR {SUM(X) / (n-1)} for xxx_SAMP agg */
1033  if (qdata_divide_dbval (func_p->value, &dbval, &xavg_1val, double_domain_ptr) != NO_ERROR)
1034  {
1035  goto error;
1036  }
1037 
1038  /* compute AVG(X) * {SUM(X) / (n)} , AVG(X) * {SUM(X) / (n-1)} for xxx_SAMP agg */
1039  if (qdata_multiply_dbval (&xavgval, &xavg_1val, &xavg2val, double_domain_ptr) != NO_ERROR)
1040  {
1041  goto error;
1042  }
1043 
1044  /* compute VAR(X) = SUM(X^2)/(n) - AVG(X) * {SUM(X) / (n)} OR VAR(X) = SUM(X^2)/(n-1) - AVG(X) * {SUM(X) / (n-1)}
1045  * for xxx_SAMP aggregates */
1046  if (qdata_subtract_dbval (&x2avgval, &xavg2val, &varval, double_domain_ptr) != NO_ERROR)
1047  {
1048  goto error;
1049  }
1050 
1051  if (func_p->function == PT_VARIANCE || func_p->function == PT_VAR_POP || func_p->function == PT_VAR_SAMP
1052  || func_p->function == PT_STDDEV || func_p->function == PT_STDDEV_POP || func_p->function == PT_STDDEV_SAMP)
1053  {
1054  pr_clone_value (&varval, func_p->value);
1055  }
1056 
1057  if (!DB_IS_NULL (&varval)
1058  && (func_p->function == PT_STDDEV || func_p->function == PT_STDDEV_POP || func_p->function == PT_STDDEV_SAMP))
1059  {
1061  if (tp_value_coerce (&varval, &dval, double_domain_ptr) != DOMAIN_COMPATIBLE)
1062  {
1063  goto error;
1064  }
1065 
1066  dtmp = db_get_double (&dval);
1067 
1068  /* mathematically, dtmp should be zero or positive; however, due to some precision errors, in some cases it
1069  * can be a very small negative number of which we cannot extract the square root */
1070  dtmp = (dtmp < 0.0f ? 0.0f : dtmp);
1071 
1072  dtmp = sqrt (dtmp);
1073  db_make_double (&dval, dtmp);
1074 
1075  pr_clone_value (&dval, func_p->value);
1076  }
1077  }
1078 
1079 exit:
1080  /* destroy distinct temp list file */
1081  if (!is_same_group)
1082  {
1083  qfile_close_list (thread_p, func_p->list_id);
1084  qfile_destroy_list (thread_p, func_p->list_id);
1085  }
1086 
1087  return NO_ERROR;
1088 
1089 error:
1090  qfile_close_list (thread_p, func_p->list_id);
1091  qfile_destroy_list (thread_p, func_p->list_id);
1092 
1093  return ER_FAILED;
1094 }
1095 
1096 static int
1098  QFILE_LIST_SCAN_ID *scan_id)
1099 {
1100  int error = NO_ERROR;
1101  int tuple_count;
1102  double row_num_d, f_row_num_d, c_row_num_d, percentile_d;
1103  FUNC_TYPE function;
1104  double cur_group_percentile;
1105 
1106  assert (ana_p != NULL && scan_id != NULL && scan_id->status == S_OPENED);
1108 
1109  function = ana_p->function;
1110  cur_group_percentile = ana_p->info.percentile.cur_group_percentile;
1111 
1112  tuple_count = scan_id->list_id.tuple_cnt;
1113  if (tuple_count < 1)
1114  {
1115  return NO_ERROR;
1116  }
1117 
1118  if (function == PT_MEDIAN)
1119  {
1120  percentile_d = 0.5;
1121  }
1122  else
1123  {
1124  percentile_d = cur_group_percentile;
1125 
1126  if (function == PT_PERCENTILE_DISC)
1127  {
1128  percentile_d = ceil (percentile_d * tuple_count) / tuple_count;
1129  }
1130  }
1131 
1132  row_num_d = ((double) (tuple_count - 1)) * percentile_d;
1133  f_row_num_d = floor (row_num_d);
1134 
1135  if (function == PT_PERCENTILE_DISC)
1136  {
1137  c_row_num_d = f_row_num_d;
1138  }
1139  else
1140  {
1141  c_row_num_d = ceil (row_num_d);
1142  }
1143 
1144  error =
1145  qdata_get_interpolation_function_result (thread_p, scan_id, scan_id->list_id.type_list.domp[0], 0, row_num_d,
1146  f_row_num_d, c_row_num_d, ana_p->value, &ana_p->domain,
1147  ana_p->function);
1148 
1149  if (error == NO_ERROR)
1150  {
1151  ana_p->opr_dbtype = TP_DOMAIN_TYPE (ana_p->domain);
1152  }
1153 
1154  return error;
1155 }
#define QFILE_TUPLE_VALUE_HEADER_SIZE
Definition: query_list.h:229
int data_readval(struct or_buf *buf, DB_VALUE *value, const tp_domain *domain, int size, bool copy, char *copy_buf, int copy_buf_len) const
TP_DOMAIN_STATUS tp_value_coerce(const DB_VALUE *src, DB_VALUE *dest, const TP_DOMAIN *desired_domain)
analytic_ntile_function_info ntile
int db_value_coerce(const DB_VALUE *src, DB_VALUE *dest, const DB_DOMAIN *desired_domain)
Definition: db_macro.c:1779
#define NO_ERROR
Definition: error_code.h:46
int pr_data_writeval_disk_size(DB_VALUE *value)
static int qdata_analytic_interpolation(cubthread::entry *thread_p, cubxasl::analytic_list_node *ana_p, QFILE_LIST_SCAN_ID *scan_id)
SCAN_CODE
QFILE_TUPLE_VALUE_TYPE_LIST type_list
Definition: query_list.h:428
int data_writeval(struct or_buf *buf, const DB_VALUE *value) const
#define ER_TF_BUFFER_OVERFLOW
Definition: error_code.h:388
int db_get_int(const DB_VALUE *value)
DB_TYPE
Definition: dbtype_def.h:670
DB_C_DOUBLE db_get_double(const DB_VALUE *value)
#define ER_FAILED
Definition: error_code.h:47
#define ER_PERCENTILE_FUNC_INVALID_PERCENTILE_RANGE
Definition: error_code.h:1505
SCAN_CODE qfile_scan_list_next(THREAD_ENTRY *thread_p, QFILE_LIST_SCAN_ID *scan_id_p, QFILE_TUPLE_RECORD *tuple_record_p, int peek)
Definition: list_file.c:4724
#define OR_BUF_INIT(buf, data, size)
#define ER_QPROC_INVALID_XASLNODE
Definition: error_code.h:532
#define assert_release(e)
Definition: error_manager.h:96
int fetch_copy_dbval(THREAD_ENTRY *thread_p, REGU_VARIABLE *regu_var, val_descr *vd, OID *class_oid, OID *obj_oid, QFILE_TUPLE tpl, DB_VALUE *dbval)
Definition: fetch.c:4466
FUNC_TYPE
DB_VALUE_COMPARE_RESULT cmpval(const DB_VALUE *value, const DB_VALUE *value2, int do_coercion, int total_order, int *start_colp, int collation) const
TP_DOMAIN * tp_domain_resolve_value(const DB_VALUE *val, TP_DOMAIN *dbuf)
int er_errid(void)
#define QPROC_IS_INTERPOLATION_FUNC(func_p)
Definition: xasl.h:531
enum tp_domain_status TP_DOMAIN_STATUS
int qdata_subtract_dbval(DB_VALUE *dbval1_p, DB_VALUE *dbval2_p, DB_VALUE *result_p, tp_domain *domain_p)
regu_variable_node operand
DB_DOMAIN_INFO domain
Definition: dbtype_def.h:1082
int qdata_multiply_dbval(DB_VALUE *dbval1_p, DB_VALUE *dbval2_p, DB_VALUE *result_p, tp_domain *domain_p)
TP_DOMAIN tp_Double_domain
int qdata_divide_dbval(DB_VALUE *dbval1_p, DB_VALUE *dbval2_p, DB_VALUE *result_p, tp_domain *domain_p)
#define QFILE_GET_TUPLE_VALUE_FLAG(ptr)
Definition: query_list.h:250
PR_TYPE * pr_type_from_id(DB_TYPE id)
TP_DOMAIN * tp_domain_resolve_default(DB_TYPE type)
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
analytic_percentile_function_info percentile
#define assert(x)
int tp_domain_status_er_set(TP_DOMAIN_STATUS status, const char *file_name, const int line_no, const DB_VALUE *src, const TP_DOMAIN *domain)
void qfile_destroy_list(THREAD_ENTRY *thread_p, QFILE_LIST_ID *list_id_p)
Definition: list_file.c:2163
int qdata_evaluate_analytic_func(cubthread::entry *thread_p, ANALYTIC_TYPE *func_p, VAL_DESCR *val_desc_p)
int fetch_peek_dbval(THREAD_ENTRY *thread_p, REGU_VARIABLE *regu_var, val_descr *vd, OID *class_oid, OID *obj_oid, QFILE_TUPLE tpl, DB_VALUE **peek_dbval)
Definition: fetch.c:3773
#define DB_VALUE_DOMAIN_TYPE(value)
Definition: dbtype.h:70
#define DB_INT32_MAX
Definition: dbtype_def.h:633
#define TP_IS_NUMERIC_TYPE(typeid)
int qdata_get_interpolation_function_result(THREAD_ENTRY *thread_p, QFILE_LIST_SCAN_ID *scan_id, tp_domain *domain, int pos, double row_num_d, double f_row_num_d, double c_row_num_d, DB_VALUE *result, tp_domain **result_dom, FUNC_TYPE function)
#define ER_PERCENTILE_FUNC_PERCENTILE_CHANGED_IN_GROUP
Definition: error_code.h:1506
TP_DOMAIN_STATUS tp_value_cast(const DB_VALUE *src, DB_VALUE *dest, const TP_DOMAIN *desired_domain, bool implicit_coercion)
#define TP_DOMAIN_TYPE(dom)
#define QFILE_GET_TUPLE_VALUE_LENGTH(ptr)
Definition: query_list.h:253
SORT_LIST * sort_list
Definition: query_list.h:429
#define NULL
Definition: freelistheap.h:34
#define QFILE_TUPLE_LENGTH_SIZE
Definition: query_list.h:224
struct pr_type * type
Definition: object_domain.h:76
int qdata_add_dbval(DB_VALUE *dbval1_p, DB_VALUE *dbval2_p, DB_VALUE *result_p, tp_domain *domain_p)
#define ANALYTIC_KEEP_RANK
int qdata_finalize_analytic_func(cubthread::entry *thread_p, ANALYTIC_TYPE *func_p, bool is_same_group)
#define err(fd,...)
Definition: porting.h:431
#define db_private_free_and_init(thrd, ptr)
Definition: memory_alloc.h:141
void or_init(OR_BUF *buf, char *data, int length)
#define db_private_alloc(thrd, size)
Definition: memory_alloc.h:227
int pr_clear_value(DB_VALUE *value)
int qfile_open_list_scan(QFILE_LIST_ID *list_id_p, QFILE_LIST_SCAN_ID *scan_id_p)
Definition: list_file.c:4658
int qdata_initialize_analytic_func(cubthread::entry *thread_p, ANALYTIC_TYPE *func_p, QUERY_ID query_id)
#define ANALYTIC_FUNC_CLEAR_FLAG(x, f)
#define DB_DEFAULT_SCALE
Definition: dbtype_def.h:561
struct db_domain_info::general_info general_info
#define TP_IS_CHAR_TYPE(typeid)
static void error(const char *msg)
Definition: gencat.c:331
#define DB_DEFAULT_PRECISION
Definition: dbtype_def.h:558
#define ER_NTILE_INVALID_BUCKET_NUMBER
Definition: error_code.h:1398
void qfile_close_scan(THREAD_ENTRY *thread_p, QFILE_LIST_SCAN_ID *scan_id_p)
Definition: list_file.c:4774
void qfile_free_list_id(QFILE_LIST_ID *list_id_p)
Definition: list_file.c:563
#define ARG_FILE_LINE
Definition: error_manager.h:44
analytic_function_info info
QFILE_LIST_ID list_id
Definition: query_list.h:507
int pr_clone_value(const DB_VALUE *src, DB_VALUE *dest)
int qfile_add_item_to_list(THREAD_ENTRY *thread_p, char *item_p, int item_size, QFILE_LIST_ID *list_id_p)
Definition: list_file.c:2330
SCAN_STATUS status
Definition: query_list.h:498
int qfile_copy_list_id(QFILE_LIST_ID *dest_list_id_p, const QFILE_LIST_ID *src_list_id_p, bool is_include_sort_list)
Definition: list_file.c:433
QFILE_LIST_ID * qfile_open_list(THREAD_ENTRY *thread_p, QFILE_TUPLE_VALUE_TYPE_LIST *type_list_p, SORT_LIST *sort_list_p, QUERY_ID query_id, int flag)
Definition: list_file.c:1142
#define DB_VALUE_TYPE(value)
Definition: dbtype.h:72
int db_make_null(DB_VALUE *value)
QFILE_LIST_ID * qfile_sort_list(THREAD_ENTRY *thread_p, QFILE_LIST_ID *list_id_p, SORT_LIST *sort_list_p, QUERY_OPTIONS option, bool do_close)
Definition: list_file.c:4030
void qfile_close_list(THREAD_ENTRY *thread_p, QFILE_LIST_ID *list_id_p)
Definition: list_file.c:1263
#define DB_IS_NULL(value)
Definition: dbtype.h:63
int db_make_double(DB_VALUE *value, const DB_C_DOUBLE num)
bool qdata_copy_db_value(DB_VALUE *dest_p, const DB_VALUE *src_p)
Definition: query_opfunc.c:310
#define ER_ARG_CAN_NOT_BE_CASTED_TO_DESIRED_DOMAIN
Definition: error_code.h:1419
int setval(DB_VALUE *dest, const DB_VALUE *src, bool copy) const
int db_make_int(DB_VALUE *value, const int num)
int collation_id
Definition: object_domain.h:92
#define ER_QPROC_INVALID_DATATYPE
Definition: error_code.h:534
#define PEEK
Definition: file_io.h:74
TP_DOMAIN * domain
Definition: regu_var.hpp:175
const char * fcode_get_uppercase_name(FUNC_TYPE ftype)
#define ANALYTIC_FUNC_IS_FLAGED(x, f)
int db_value_domain_init(DB_VALUE *value, const DB_TYPE type, const int precision, const int scale)
Definition: db_macro.c:153
#define TP_DOMAIN_COLLATION_FLAG(dom)