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(name) (strcmp((name), "quantile") == 0 || strcmp((name), "quantile_avg") == 0 || \
21 : strcmp((name), "median") == 0 || strcmp((name), "median_avg") == 0)
22 :
23 : static sql_rel *
24 1425123 : rel_add_orderby(visitor *v, sql_rel *rel)
25 : {
26 1425123 : if (is_groupby(rel->op)) {
27 17546 : if (rel->exps && !rel->r) { /* find quantiles */
28 4451 : sql_exp *obe = NULL, *oberef = NULL;
29 9362 : for(node *n = rel->exps->h; n; n = n->next) {
30 4911 : sql_exp *e = n->data;
31 :
32 4911 : if (is_aggr(e->type)) {
33 4900 : sql_subfunc *af = e->f;
34 4900 : list *aa = e->l;
35 :
36 : /* for now we only handle one sort order */
37 4900 : if (IS_ORDER_BASED_AGGR(af->func->base.name) && aa && list_length(aa) == 2) {
38 28 : sql_exp *nobe = aa->h->data;
39 28 : if (nobe && !obe) {
40 21 : sql_rel *l = rel->l = rel_project(v->sql->sa, rel->l, rel_projections(v->sql, rel->l, NULL, 1, 1));
41 21 : obe = nobe;
42 21 : oberef = nobe;
43 21 : if (l) {
44 21 : if (!is_alias(nobe->type)) {
45 0 : oberef = nobe = exp_label(v->sql->sa, exp_copy(v->sql, nobe), ++v->sql->label);
46 0 : append(l->exps, nobe);
47 : }
48 21 : set_nulls_first(nobe);
49 21 : set_ascending(nobe);
50 21 : aa->h->data = exp_ref(v->sql, nobe);
51 21 : list *o = l->r = sa_list(v->sql->sa);
52 21 : if (o)
53 21 : append(o, nobe);
54 : }
55 7 : } else if (exp_match_exp(nobe, obe)) {
56 3 : aa->h->data = exp_ref(v->sql, oberef);
57 : }
58 : }
59 : }
60 : }
61 : return rel;
62 : }
63 : }
64 : return rel;
65 : }
66 :
67 : static sql_exp *
68 6682049 : exp_timezone(visitor *v, sql_rel *rel, sql_exp *e, int depth)
69 : {
70 6682049 : (void)depth;
71 6682049 : (void)rel;
72 6682049 : if (e && e->type == e_func) {
73 163466 : list *l = e->l;
74 163466 : sql_subfunc *f = e->f;
75 163466 : const char *fname = f->func->base.name;
76 163466 : if (list_length(l) == 2) {
77 98688 : if (strcmp(fname, "timestamp_to_str") == 0 || strcmp(fname, "time_to_str") == 0) {
78 10 : sql_exp *e = l->h->data;
79 10 : sql_subtype *t = exp_subtype(e);
80 10 : if (t->type->eclass == EC_TIMESTAMP_TZ || t->type->eclass == EC_TIME_TZ) {
81 7 : sql_exp *offset = exp_atom_lng(v->sql->sa, v->sql->timezone);
82 7 : list_append(l, offset);
83 : }
84 98678 : } else if (strcmp(fname, "str_to_timestamp") == 0 || strcmp(fname, "str_to_time") == 0 || strcmp(fname, "str_to_date") == 0) {
85 52 : sql_exp *offset = exp_atom_lng(v->sql->sa, v->sql->timezone);
86 52 : list_append(l, offset);
87 : }
88 : }
89 : }
90 6682049 : return e;
91 : }
92 :
93 : sql_rel *
94 572419 : rel_physical(mvc *sql, sql_rel *rel)
95 : {
96 572419 : visitor v = { .sql = sql };
97 :
98 572419 : rel = rel_visitor_bottomup(&v, rel, &rel_add_orderby);
99 572401 : rel = rel_exp_visitor_topdown(&v, rel, &exp_timezone, true);
100 :
101 : #ifdef HAVE_HGE
102 572401 : if (rel && sql->no_int128) {
103 0 : sql_rel *r = rel;
104 0 : if (is_topn(r->op))
105 0 : r = r->l;
106 0 : if (r && is_project(r->op) && !list_empty(r->exps)) {
107 0 : for (node *n = r->exps->h; n; n = n->next) {
108 0 : sql_exp *e = n->data;
109 :
110 0 : if (exp_subtype(e)->type->localtype == TYPE_hge) /* down cast */
111 0 : e = n->data = exp_convert(sql, e, exp_subtype(e), sql_bind_localtype("lng"));
112 : }
113 : }
114 : }
115 : #endif
116 572401 : return rel;
117 : }
|