Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #include "monetdb_config.h"
14 : #include "rel_physical.h"
15 : #include "rel_optimizer_private.h"
16 : #include "rel_rewriter.h"
17 : #include "rel_exp.h"
18 : #include "rel_rel.h"
19 :
20 : #define IS_ORDER_BASED_AGGR(fname, argc) (\
21 : (argc == 2 && (strcmp((fname), "quantile") == 0 || strcmp((fname), "quantile_avg") == 0)) || \
22 : (argc == 1 && (strcmp((fname), "median") == 0 || strcmp((fname), "median_avg") == 0)))
23 :
24 : static sql_rel *
25 1241277 : rel_add_orderby(visitor *v, sql_rel *rel)
26 : {
27 1241277 : if (is_groupby(rel->op)) {
28 16744 : if (rel->exps && !rel->r) { /* find quantiles */
29 4443 : sql_exp *obe = NULL, *oberef = NULL;
30 9346 : for(node *n = rel->exps->h; n; n = n->next) {
31 4903 : sql_exp *e = n->data;
32 :
33 4903 : if (is_aggr(e->type)) {
34 4892 : sql_subfunc *af = e->f;
35 4892 : list *aa = e->l;
36 :
37 : /* for now we only handle one sort order */
38 4892 : if (aa && IS_ORDER_BASED_AGGR(af->func->base.name, list_length(aa))) {
39 52 : sql_exp *nobe = aa->h->data;
40 52 : if (nobe && !obe) {
41 43 : sql_rel *l = rel->l = rel_project(v->sql->sa, rel->l, rel_projections(v->sql, rel->l, NULL, 1, 1));
42 43 : obe = nobe;
43 43 : oberef = nobe;
44 43 : if (l) {
45 43 : if (!is_alias(nobe->type)) {
46 3 : oberef = nobe = exp_label(v->sql->sa, exp_copy(v->sql, nobe), ++v->sql->label);
47 3 : append(l->exps, nobe);
48 : }
49 43 : set_nulls_first(nobe);
50 43 : set_ascending(nobe);
51 43 : aa->h->data = exp_ref(v->sql, nobe);
52 43 : list *o = l->r = sa_list(v->sql->sa);
53 43 : if (o)
54 43 : append(o, nobe);
55 : }
56 9 : } else if (exp_match_exp(nobe, obe)) {
57 7 : aa->h->data = exp_ref(v->sql, oberef);
58 : }
59 : }
60 : }
61 : }
62 : return rel;
63 : }
64 : }
65 : return rel;
66 : }
67 :
68 : static sql_exp *
69 5583473 : exp_timezone(visitor *v, sql_rel *rel, sql_exp *e, int depth)
70 : {
71 5583473 : (void)depth;
72 5583473 : (void)rel;
73 5583473 : if (e && e->type == e_func) {
74 153882 : list *l = e->l;
75 153882 : sql_subfunc *f = e->f;
76 153882 : const char *fname = f->func->base.name;
77 153882 : if (list_length(l) == 2) {
78 93416 : if (strcmp(fname, "timestamp_to_str") == 0 || strcmp(fname, "time_to_str") == 0) {
79 10 : sql_exp *e = l->h->data;
80 10 : sql_subtype *t = exp_subtype(e);
81 10 : if (t->type->eclass == EC_TIMESTAMP_TZ || t->type->eclass == EC_TIME_TZ) {
82 7 : sql_exp *offset = exp_atom_lng(v->sql->sa, v->sql->timezone);
83 7 : list_append(l, offset);
84 : }
85 93406 : } else if (strcmp(fname, "str_to_timestamp") == 0 || strcmp(fname, "str_to_time") == 0 || strcmp(fname, "str_to_date") == 0) {
86 52 : sql_exp *offset = exp_atom_lng(v->sql->sa, v->sql->timezone);
87 52 : list_append(l, offset);
88 : }
89 : }
90 : }
91 5583473 : return e;
92 : }
93 :
94 : sql_rel *
95 522676 : rel_physical(mvc *sql, sql_rel *rel)
96 : {
97 522676 : visitor v = { .sql = sql };
98 :
99 522676 : rel = rel_visitor_bottomup(&v, rel, &rel_add_orderby);
100 522655 : rel = rel_exp_visitor_topdown(&v, rel, &exp_timezone, true);
101 :
102 : #ifdef HAVE_HGE
103 522648 : if (rel && sql->no_int128) {
104 0 : sql_rel *r = rel;
105 0 : if (is_topn(r->op))
106 0 : r = r->l;
107 0 : if (r && is_project(r->op) && !list_empty(r->exps)) {
108 0 : for (node *n = r->exps->h; n; n = n->next) {
109 0 : sql_exp *e = n->data;
110 :
111 0 : if (exp_subtype(e)->type->localtype == TYPE_hge) /* down cast */
112 0 : e = n->data = exp_convert(sql, e, exp_subtype(e), sql_bind_localtype("lng"));
113 : }
114 : }
115 : }
116 : #endif
117 522648 : return rel;
118 : }
|