• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

estebanzimanyi / MobilityDB / 7167908858

11 Dec 2023 12:10PM UTC coverage: 95.302% (+0.1%) from 95.184%
7167908858

push

github

web-flow
Improve span operations (#407)

* Improve span ops

* Improve function names

* Improve documentation

1631 of 1664 new or added lines in 80 files covered. (98.02%)

22 existing lines in 6 files now uncovered.

31081 of 32613 relevant lines covered (95.3%)

770010.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.05
/mobilitydb/src/general/span_aggfuncs.c
1
/*****************************************************************************
2
 *
3
 * This MobilityDB code is provided under The PostgreSQL License.
4
 * Copyright (c) 2016-2023, Université libre de Bruxelles and MobilityDB
5
 * contributors
6
 *
7
 * MobilityDB includes portions of PostGIS version 3 source code released
8
 * under the GNU General Public License (GPLv2 or later).
9
 * Copyright (c) 2001-2023, PostGIS contributors
10
 *
11
 * Permission to use, copy, modify, and distribute this software and its
12
 * documentation for any purpose, without fee, and without a written
13
 * agreement is hereby granted, provided that the above copyright notice and
14
 * this paragraph and the following two paragraphs appear in all copies.
15
 *
16
 * IN NO EVENT SHALL UNIVERSITE LIBRE DE BRUXELLES BE LIABLE TO ANY PARTY FOR
17
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
18
 * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
19
 * EVEN IF UNIVERSITE LIBRE DE BRUXELLES HAS BEEN ADVISED OF THE POSSIBILITY
20
 * OF SUCH DAMAGE.
21
 *
22
 * UNIVERSITE LIBRE DE BRUXELLES SPECIFICALLY DISCLAIMS ANY WARRANTIES,
23
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
24
 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON
25
 * AN "AS IS" BASIS, AND UNIVERSITE LIBRE DE BRUXELLES HAS NO OBLIGATIONS TO
26
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
27
 *
28
 *****************************************************************************/
29

30
/**
31
 * @file
32
 * @brief Aggregate function for span types
33
 */
34

35
/* C */
36
#include <assert.h>
37
/* PostgreSQL */
38
#include <postgres.h>
39
#include <fmgr.h>
40
#include <utils/array.h>
41
/* MEOS */
42
#include <meos.h>
43
#include <meos_internal.h>
44
#include "general/temporal.h"
45
#include "general/type_util.h"
46
#include "general/set.h"
47
#include "general/span.h"
48
/* MobilityDB */
49
#include "pg_general/meos_catalog.h"
50

51
/*****************************************************************************/
52

53
PGDLLEXPORT Datum Span_extent_transfn(PG_FUNCTION_ARGS);
54
PG_FUNCTION_INFO_V1(Span_extent_transfn);
15✔
55
/**
56
 * @brief Transition function for extent aggregation of span values
57
 */
58
Datum
59
Span_extent_transfn(PG_FUNCTION_ARGS)
20,746✔
60
{
61
  Span *s1 = PG_ARGISNULL(0) ? NULL : PG_GETARG_SPAN_P(0);
20,746✔
62
  Span *s2 = PG_ARGISNULL(1) ? NULL : PG_GETARG_SPAN_P(1);
20,746✔
63
  Span *result = span_extent_transfn(s1, s2);
20,746✔
64
  if (! result)
20,746✔
65
    PG_RETURN_NULL();
249✔
66
  PG_RETURN_POINTER(result);
20,497✔
67
}
68

69
PGDLLEXPORT Datum Span_extent_combinefn(PG_FUNCTION_ARGS);
70
PG_FUNCTION_INFO_V1(Span_extent_combinefn);
8✔
71
/**
72
 * @brief Combine function for temporal extent aggregation
73
 */
74
Datum
75
Span_extent_combinefn(PG_FUNCTION_ARGS)
31✔
76
{
77
  Span *s1 = PG_ARGISNULL(0) ? NULL : PG_GETARG_SPAN_P(0);
31✔
78
  Span *s2 = PG_ARGISNULL(1) ? NULL : PG_GETARG_SPAN_P(1);
31✔
79
  if (! s2 && ! s1)
31✔
80
    PG_RETURN_NULL();
×
81
  if (s1 && ! s2)
31✔
82
    PG_RETURN_POINTER(s1);
20✔
83
  if (s2 && ! s1)
11✔
84
    PG_RETURN_POINTER(s2);
11✔
85
  /* Non-strict union */
NEW
86
  Span *result = super_union_span_span(s1, s2);
×
87
  PG_RETURN_POINTER(result);
×
88
}
89

90
/*****************************************************************************/
91

92
PGDLLEXPORT Datum Spanbase_extent_transfn(PG_FUNCTION_ARGS);
93
PG_FUNCTION_INFO_V1(Spanbase_extent_transfn);
9✔
94
/**
95
 * @brief Transition function for extent aggregation of base values of span
96
 * types
97
 */
98
Datum
99
Spanbase_extent_transfn(PG_FUNCTION_ARGS)
140✔
100
{
101
  if (PG_ARGISNULL(0) && PG_ARGISNULL(1))
140✔
102
    PG_RETURN_NULL();
40✔
103
  Span *s = PG_ARGISNULL(0) ? NULL : PG_GETARG_SPAN_P(0);
100✔
104
  if (PG_ARGISNULL(1))
100✔
105
    PG_RETURN_POINTER(s);
1✔
106
  Datum d = PG_GETARG_DATUM(1);
99✔
107
  meosType basetype = oid_type(get_fn_expr_argtype(fcinfo->flinfo, 1));
99✔
108
  s = spanbase_extent_transfn(s, d, basetype);
99✔
109
  PG_RETURN_POINTER(s);
99✔
110
}
111

112
PGDLLEXPORT Datum Set_extent_transfn(PG_FUNCTION_ARGS);
113
PG_FUNCTION_INFO_V1(Set_extent_transfn);
9✔
114
/**
115
 * @brief Transition function for extent aggregation of set values
116
 */
117
Datum
118
Set_extent_transfn(PG_FUNCTION_ARGS)
146✔
119
{
120
  Span *span = PG_ARGISNULL(0) ? NULL : PG_GETARG_SPAN_P(0);
146✔
121
  Set *set = PG_ARGISNULL(1) ? NULL : PG_GETARG_SET_P(1);
146✔
122
  span = set_extent_transfn(span, set);
146✔
123
  PG_FREE_IF_COPY(set, 1);
146✔
124
  if (! span)
146✔
125
    PG_RETURN_NULL();
44✔
126
  PG_RETURN_POINTER(span);
102✔
127
}
128

129
PGDLLEXPORT Datum Spanset_extent_transfn(PG_FUNCTION_ARGS);
130
PG_FUNCTION_INFO_V1(Spanset_extent_transfn);
9✔
131
/**
132
 * @brief Transition function for extent aggregation of span set values
133
 */
134
Datum
135
Spanset_extent_transfn(PG_FUNCTION_ARGS)
146✔
136
{
137
  Span *s = PG_ARGISNULL(0) ? NULL : PG_GETARG_SPAN_P(0);
146✔
138
  SpanSet *ss = PG_ARGISNULL(1) ? NULL : PG_GETARG_SPANSET_P(1);
146✔
139
  s = spanset_extent_transfn(s, ss);
146✔
140
  PG_FREE_IF_COPY(ss, 1);
146✔
141
  if (! s)
146✔
142
    PG_RETURN_NULL();
44✔
143
  PG_RETURN_POINTER(s);
102✔
144
}
145

146
/*****************************************************************************/
147

148
/*
149
 * The transition and combine functions for span_union are, respectively,
150
 * PostgreSQL's array_agg_transfn and array_agg_combinefn. Similarly, the
151
 * combine function for spanset_union is PostgreSQL's array_agg_combinefn.
152
 * The idea is that all the component spans are simply appened to an array
153
 * without any processing and thus are not sorted. The final function then
154
 * extract the spans, sort them, and performs the normalization.
155
 * Reusing PostgreSQL array function enables us to leverage parallel aggregates
156
 * (introduced in PostgreSQL version 16) and other built-in optimizations.
157
 */
158

159
PGDLLEXPORT Datum Spanset_union_transfn(PG_FUNCTION_ARGS);
160
PG_FUNCTION_INFO_V1(Spanset_union_transfn);
6✔
161
/*
162
 * @brief Transition function for aggregating span sets
163
 *
164
 * All we do here is gather the input span sets' spans into an array so
165
 * that the final function can sort and combine them.
166
 */
167
Datum
168
Spanset_union_transfn(PG_FUNCTION_ARGS)
108✔
169
{
170
  MemoryContext aggContext;
171
  if (! AggCheckCallContext(fcinfo, &aggContext))
108✔
172
    elog(ERROR, "Spanset_union_transfn called in non-aggregate context");
×
173

174
  Oid spansetoid = get_fn_expr_argtype(fcinfo->flinfo, 1);
108✔
175
  meosType spansettype = oid_type(spansetoid);
108✔
176
  assert(spanset_type(spansettype));
177
  meosType spantype = spansettype_spantype(spansettype);
108✔
178
  Oid spanoid = type_oid(spantype);
108✔
179

180
  ArrayBuildState *state;
181
  if (PG_ARGISNULL(0))
108✔
182
    state = initArrayResult(spanoid, aggContext, false);
5✔
183
  else
184
    state = (ArrayBuildState *) PG_GETARG_POINTER(0);
103✔
185

186
  /* Skip NULLs */
187
  if (! PG_ARGISNULL(1))
108✔
188
  {
189
    SpanSet *ss = PG_GETARG_SPANSET_P(1);
103✔
190
    for (int i = 0; i < ss->count; i++)
586✔
191
      accumArrayResult(state, SpanPGetDatum(SPANSET_SP_N(ss, i)), false,
483✔
192
        spanoid, aggContext);
193
  }
194
  PG_RETURN_POINTER(state);
108✔
195
}
196

197
PGDLLEXPORT Datum Span_union_finalfn(PG_FUNCTION_ARGS);
198
PG_FUNCTION_INFO_V1(Span_union_finalfn);
6✔
199
/*
200
 * @brief Final function for union aggregation of spans.
201
 * @note Shared by Span_union_finalfn() and Spanset_union_finalfn().
202
 */
203
Datum
204
Span_union_finalfn(PG_FUNCTION_ARGS)
11✔
205
{
206
  /* cannot be called directly because of internal-type argument */
207
  Assert(AggCheckCallContext(fcinfo, NULL));
208
  // MemoryContext aggContext;
209
  // if (! AggCheckCallContext(fcinfo, &aggContext))
210
    // elog(ERROR, "Span_union_finalfn called in non-aggregate context");
211

212
  ArrayBuildState *state = PG_ARGISNULL(0) ? NULL :
11✔
213
    (ArrayBuildState *) PG_GETARG_POINTER(0);
11✔
214
  if (state == NULL)
11✔
215
    /* This shouldn't be possible, but just in case.... */
216
    PG_RETURN_NULL();
×
217

218
  /* Also return NULL if we had zero inputs, like other aggregates */
219
  int32 count = state->nelems;
11✔
220
  if (count == 0)
11✔
221
    PG_RETURN_NULL();
1✔
222

223
  Span *spans = palloc0(sizeof(Span) * count);
10✔
224
  int k = 0;
225
  for (int i = 0; i < count; i++)
10,601✔
226
  {
227
    if (! state->dnulls[i])
10,591✔
228
      spans[k++] = *(DatumGetSpanP(state->dvalues[i]));
10,186✔
229
  }
230

231
  /* Also return NULL if we had only null inputs */
232
  if (k == 0)
10✔
233
    PG_RETURN_NULL();
1✔
234

235
  int newcount;
236
  Span *normspans = spanarr_normalize(spans, k, ORDERED_NO, &newcount);
9✔
237
  SpanSet *result = spanset_make_free(normspans, newcount, NORMALIZE_NO);
9✔
238

239
  /* Free memory */
240
  pfree(spans);
9✔
241

242
  PG_RETURN_POINTER(result);
9✔
243
}
244

245
/*****************************************************************************/
246

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc