File: temporal_types_p2.xml

package info (click to toggle)
mobilitydb 1.3.0~alpha-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 118,528 kB
  • sloc: ansic: 166,361; sql: 99,983; xml: 22,860; yacc: 447; makefile: 200; lex: 151; sh: 142
file content (624 lines) | stat: -rw-r--r-- 43,170 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
<?xml version="1.0" encoding="UTF-8"?>
<!--
   ****************************************************************************
    MobilityDB Manual
    Copyright(c) MobilityDB Contributors

    This documentation is licensed under a Creative Commons Attribution-Share
    Alike 3.0 License: https://creativecommons.org/licenses/by-sa/3.0/
   ****************************************************************************
-->
<chapter xml:id="ttype_p2">
	<title>Temporal Types (Part 2)</title>

	<sect1 xml:id="ttype_modifications">
		<title>Modifications</title>
		<para>
			We explain next the semantics of the modification operations (that is, <varname>insert</varname>, <varname>update</varname>, and <varname>delete</varname>) for temporal types. These operations have similar semantics as the corresponding operations for application-time temporal tables introduced in the <ulink url="https://en.wikipedia.org/wiki/SQL:2011">SQL:2011</ulink> standard. The main difference is that SQL uses <emphasis>tuple timestamping</emphasis> (where timestamps are attached to tuples), while temporal values in MobilityDB use <emphasis>attribute timestamping</emphasis> (where timestamps are attached to attribute values). Please refer to this <ulink url="https://www.researchgate.net/publication/387302901_Reconciling_tuple_and_attribute_timestamping_for_temporal_data_warehouses">article</ulink> for a detailed discussion about tuple versus attribute timestamping in temporal databases.
		</para>

		<para>
			The <varname>insert</varname> operation adds to a temporal value the instants of another one without modifying the existing instants, as illustrated in <xref linkend="insert_fig"/>.
		</para>

		<figure xml:id="insert_fig" float="start">
			<title>Insert operation for temporal values.</title>
			<mediaobject>
				<imageobject><imagedata format="PDF" scale="100" fileref="images/insert.pdf"/></imageobject>
				<imageobject><imagedata format="SVG" scale="100" fileref="images/insert.svg"/></imageobject>
				<imageobject><imagedata format="PNG" scale="100" fileref="images/insert.png"/></imageobject>
			</mediaobject>
		</figure>

		<para>
			As shown in the figure, the temporal values may only intersect at their boundary, and in that case, they must have the same base value at their common timestamps, otherwise an error is raised. The result of the operation is the union of the instants for both temporal values, as shown in the first result of the figure. This is equivalent to a <varname>merge</varname> operation explained below. Alternatively, as shown in the second result of the figure, the inserted fragments that are disjoint with the original value are connected to the last instant before and the first instant after the fragment. A Boolean parameter <varname>connect</varname> is used to choose between the two results, and the parameter is set to true by default. Notice that this only applies to continuous temporal values.
		</para>

		<para>
			The <varname>update</varname> operation replaces the instants in the first temporal value with those of the second one as illustrated in <xref linkend="update_delete_fig"/>.
		</para>

		<figure xml:id="update_delete_fig" float="start">
			<title>Update and delete operation for temporal values.</title>
			<mediaobject>
				<imageobject><imagedata format="PDF" scale="100" fileref="images/update_delete.pdf"/></imageobject>
				<imageobject><imagedata format="SVG" scale="100" fileref="images/update_delete.svg"/></imageobject>
				<imageobject><imagedata format="PNG" scale="100" fileref="images/update_delete.png"/></imageobject>
			</mediaobject>
		</figure>

		<para>
			As in the case of an <varname>insert</varname> operation, an additional Boolean parameter determines whether the replaced disconnected fragments are connected in the resulting value, as shown in the two possible results in the figure. When the two temporal values are either disjoint or only overlap at their boundary, this corresponds to an <varname>insert</varname> operation as explained above. In this case, the <varname>update</varname> operation behaves as an <varname>upsert</varname> operation in SQL.
		</para>

		<para>
			The <varname>deleteTime</varname> operation removes the instants of a temporal value that intersect a time value. This operation can be used in two different situations, illustrated in <xref linkend="update_delete_fig"/>.
      </para>

		<orderedlist inheritnum="ignore" continuation="restarts">
			<listitem>
				<para>In the first case, shown as the top result in the figure, the meaning of operation is to introduce time gaps after removing the instants of the temporal value intersecting the time value. This is equivalent to the restriction operations (<xref linkend="ttype_restrictions"/>), which restrict a temporal value to the complement of the time value.</para>
			</listitem>

			<listitem>
				<para>The second case, shown as the bottom result in the figure, is used for removing erroneous values (e.g., detected as outliers) without introducing a time gap, or for removing time gaps. In this case, the instants of the temporal value are deleted and the last instant before and the first instant after a removed fragment are connected. This behaviour is specified by setting an additional Boolean parameter of the operation. Notice that this only applies to continuous temporal values.</para>
			</listitem>
		</orderedlist>

		<figure xml:id="modif_sql_fig" float="start">
			<title>Modification operations for temporal tables in SQL</title>
			<mediaobject>
				<imageobject><imagedata format="PDF" scale="100" fileref="images/modif_sql.pdf"/></imageobject>
				<imageobject><imagedata format="SVG" scale="100" fileref="images/modif_sql.svg"/></imageobject>
				<imageobject><imagedata format="PNG" scale="100" fileref="images/modif_sql.png"/></imageobject>
			</mediaobject>
		</figure>

		<para>
			<xref linkend="modif_sql_fig"/> shows the equivalent modification operations for temporal tables in the SQL standard. Intuitively, these figures are obtained by rotating 90 degrees clockwise the corresponding figures for temporal values (<xref linkend="insert_fig"/> and <xref linkend="update_delete_fig"/>). This follows from the fact that in SQL consecutive tuples ordered by time are typically connected through the <varname>LEAD</varname> and <varname>LAG</varname> window functions.
		</para>

		<itemizedlist>
			<listitem xml:id="insert">
				<para>Insert a temporal value into another one</para>
				<para><varname>insert(ttype,ttype,connect=true) → ttype</varname></para>
				<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT insert(tint '{1@2001-01-01, 3@2001-01-03, 5@2001-01-05}',
  tint '{3@2001-01-03, 7@2001-01-07}');
-- {1@2001-01-01, 3@2001-01-03, 5@2001-01-05, 7@2001-01-07}
SELECT insert(tint '{1@2001-01-01, 3@2001-01-03, 5@2001-01-05}',
  tint '{5@2001-01-03, 7@2001-01-07}');
-- ERROR: The temporal values have different value at their overlapping instant 2001-01-03
SELECT insert(tfloat '[1@2001-01-01, 2@2001-01-02]',
  tfloat '[1@2001-01-03, 1@2001-01-05]');
-- [1@2001-01-01, 2@2001-01-02, 1@2001-01-03, 1@2001-01-05]
SELECT insert(tfloat '[1@2001-01-01, 2@2001-01-02]',
  tfloat '[1@2001-01-03, 1@2001-01-05]', false);
-- {[1@2001-01-01, 2@2001-01-02], [1@2001-01-03, 1@2001-01-05]}
SELECT asText(insert(tgeompoint '{[Point(1 1 1)@2001-01-01, Point(2 2 2)@2001-01-02],
  [Point(3 3 3)@2001-01-04],[Point(1 1 1)@2001-01-05]}',
  tgeompoint 'Point(1 1 1)@2001-01-03'));
/* {[POINT Z (1 1 1)@2001-01-01, POINT Z (2 2 2)@2001-01-02, POINT Z (1 1 1)@2001-01-03,
 POINT Z (3 3 3)@2001-01-04], [POINT Z (1 1 1)@2001-01-05]} */
</programlisting>
				</listitem>

			<listitem xml:id="update">
				<para>Update a temporal value with another one</para>
				<para><varname>update(ttype,ttype,connect=true) → ttype</varname></para>
				<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT update(tint '{1@2001-01-01, 3@2001-01-03, 5@2001-01-05}',
  tint '{5@2001-01-03, 7@2001-01-07}');
-- {1@2001-01-01, 5@2001-01-03, 5@2001-01-05, 7@2001-01-07}
SELECT update(tfloat '[1@2001-01-01, 1@2001-01-05]',
  tfloat '[1@2001-01-02, 3@2001-01-03, 1@2001-01-04]');
-- {[1@2001-01-01, 1@2001-01-02, 3@2001-01-03, 1@2001-01-04, 1@2001-01-05]}
SELECT asText(update(tgeompoint '{[Point(1 1 1)@2001-01-01, Point(3 3 3)@2001-01-03,
  Point(1 1 1)@2001-01-05], [Point(1 1 1)@2001-01-07]}',
  tgeompoint '[Point(2 2 2)@2001-01-02, Point(2 2 2)@2001-01-04]'));
/* {[POINT Z (1 1 1)@2001-01-01, POINT Z (2 2 2)@2001-01-02, POINT Z (2 2 2)@2001-01-04,
  POINT Z (1 1 1)@2001-01-05], [POINT Z (1 1 1)@2001-01-07]} */
SELECT asText(update(
  tgeometry '[Point(1 1)@2001-01-01, Point(3 3)@2001-01-03, Point(1 1)@2001-01-05]',
  tgeometry '[Linestring(2 2,3 3)@2001-01-02, Linestring(3 3,2 2)@2001-01-04]'));
/* [POINT(1 1)@2001-01-01, LINESTRING(2 2,3 3)@2001-01-02, 
    LINESTRING(3 3,2 2)@2001-01-04], (POINT(3 3)@2001-01-04, POINT(1 1)@2001-01-05] */
</programlisting>
				</listitem>

			<listitem xml:id="deleteTime">
				<para>Delete the instants of a temporal value that intersect a time value</para>
				<para><varname>deleteTime(ttype,time,connect=true) → ttype</varname></para>
				<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT deleteTime(tint '[1@2001-01-01, 1@2001-01-03]', timestamptz '2001-01-02', false);
-- {[1@2001-01-01, 1@2001-01-02), (1@2001-01-02, 1@2001-01-03]}
SELECT deleteTime(tint '[1@2001-01-01, 1@2001-01-03]', timestamptz '2001-01-02');
-- [1@2001-01-01, 1@2001-01-03]
SELECT deleteTime(tfloat '[1@2001-01-01, 4@2001-01-02, 2@2001-01-04, 5@2001-01-05]',
  tstzspan '[2001-01-02, 2001-01-04]');
-- [1@2001-01-01, 5@2001-01-05]
SELECT asText(deleteTime(tgeompoint '{[Point(1 1 1)@2001-01-01,
  Point(2 2 2)@2001-01-02], [Point(3 3 3)@2001-01-04, Point(3 3 3)@2001-01-05]}',
  tstzspan '[2001-01-02, 2001-01-04]'));
/* {[POINT Z (1 1 1)@2001-01-01, POINT Z (2 2 2)@2001-01-02, POINT Z (3 3 3)@2001-01-04,
  POINT Z (3 3 3)@2001-01-05]} */
</programlisting>
				</listitem>

			<listitem xml:id="appendInstant">
				<indexterm significance="normal"><primary><varname>appendInstant</varname></primary></indexterm>
				<para>Append a temporal instant to a temporal value</para>
				<para><varname>appendInstant(ttype,ttypeInst,interp=NULL) → ttype</varname></para>
				<para><varname>appendInstant(ttypeInst,interp=NULL,maxdist=NULL,maxt=NULL) → ttypeSeq</varname></para>
				<para>The first version of the function returns the result of appending the second argument to the first one. If either input is NULL, then NULL is returned.</para>
				<para>The second version of the function above is an <emphasis>aggregate</emphasis> function that returns the result of successively appending a set of rows of temporal values. This means that it operates in the same way the <varname>SUM()</varname> and <varname>AVG()</varname> functions do and like most aggregates, it also ignores NULL values. Two optional arguments state a maximum distance and a maximum time interval such that a gap is introduced whenever two consecutive instants have a distance or a time gap greater than these values. For temporal points the distance is specified in units of the coordinate system. If one of the arguments are not given, it is not taken into account for determining the gaps.</para>
				<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT appendInstant(tint '1@2001-01-01', tint '1@2001-01-02');
-- [1@2001-01-01, 1@2001-01-02]
SELECT appendInstant(tint '1@2001-01-01', tint '1@2001-01-02', 'discrete');
-- {1@2001-01-01, 1@2001-01-02}
SELECT appendInstant(tint '[1@2001-01-01]', tint '1@2001-01-02');
-- [1@2001-01-01, 1@2001-01-02]
SELECT asText(appendInstant(tgeompoint '{[Point(1 1 1)@2001-01-01,
  Point(2 2 2)@2001-01-02], [Point(3 3 3)@2001-01-04, Point(3 3 3)@2001-01-05]}',
  tgeompoint 'Point(1 1 1)@2001-01-06'));
/* {[POINT Z (1 1 1)@2001-01-01, POINT Z (2 2 2)@2001-01-02],
   [POINT Z (3 3 3)@2001-01-04, POINT Z (3 3 3)@2001-01-05,
   POINT Z (1 1 1)@2001-01-06]} */
SELECT asText(appendInstant(tgeometry '{[Point(1 1)@2001-01-01, Point(2 2)@2001-01-02], 
  [Linestring(2 2,3 3)@2001-01-04, Point(3 3)@2001-01-05]}',
  tgeometry 'Linestring(1 1,2 2)@2001-01-06'));
/* {[POINT(1 1)@2001-01-01, POINT(2 2)@2001-01-02], [LINESTRING(2 2,3 3)@2001-01-04, 
     POINT(3 3)@2001-01-05, LINESTRING(1 1,2 2)@2001-01-06]} */
</programlisting>
				<programlisting language="sql" xml:space="preserve" format="linespecific">
WITH temp(inst) AS (
  SELECT tfloat '1@2001-01-01' UNION SELECT tfloat '2@2001-01-02' UNION
  SELECT tfloat '3@2001-01-03' UNION SELECT tfloat '4@2001-01-04' UNION
  SELECT tfloat '5@2001-01-05' )
SELECT appendInstant(inst ORDER BY inst) FROM temp;
-- [1@2001-01-01, 5@2001-01-05]
WITH temp(inst) AS (
  SELECT tfloat '1@2001-01-01' UNION SELECT tfloat '2@2001-01-02' UNION
  SELECT tfloat '3@2001-01-03' UNION SELECT tfloat '4@2001-01-04' UNION
  SELECT tfloat '5@2001-01-05' )
SELECT appendInstant(inst, 'discrete' ORDER BY inst) FROM temp;
-- {1@2001-01-01, 2@2001-01-02, 3@2001-01-03, 4@2001-01-04, 5@2001-01-05}
WITH temp(inst) AS (
  SELECT tgeogpoint 'Point(1 1)@2001-01-01' UNION
  SELECT tgeogpoint 'Point(2 2)@2001-01-02' UNION
  SELECT tgeogpoint 'Point(3 3)@2001-01-03' UNION
  SELECT tgeogpoint 'Point(4 4)@2001-01-04' UNION
  SELECT tgeogpoint 'Point(5 5)@2001-01-05' )
SELECT asText(appendInstant(inst ORDER BY inst)) FROM temp;
/* [POINT(1 1)@2001-01-01, POINT(2 2)@2001-01-02, POINT(3 3)@2001-01-03,
   POINT(4 4)@2001-01-04, POINT(5 5)@2001-01-05] */
</programlisting>
				<para>Notice that in the first query above with <varname>tfloat</varname>, the intermediate observations were removed by the normalization process since they were redundant due to linear interpolation. This is not the case for the second query with discrete interpolation or the third query with <varname>tgeogpoint</varname>, where geodetic coordinates are used.</para>
				<programlisting language="sql" xml:space="preserve" format="linespecific">
WITH temp(inst) AS (
  SELECT tfloat '1@2001-01-01' UNION SELECT tfloat '2@2001-01-02' UNION
  SELECT tfloat '4@2001-01-04' UNION SELECT tfloat '5@2001-01-05' UNION
  SELECT tfloat '7@2001-01-07' )
SELECT appendInstant(inst, NULL, 0.0, '1 day' ORDER BY inst) FROM temp;
-- {[1@2001-01-01, 2@2001-01-02], [4@2001-01-04, 5@2001-01-05], [7@2001-01-07]}
WITH temp(inst) AS (
  SELECT tgeompoint 'Point(1 1)@2001-01-01' UNION
  SELECT tgeompoint 'Point(2 2)@2001-01-02' UNION
  SELECT tgeompoint 'Point(4 4)@2001-01-04' UNION
  SELECT tgeompoint 'Point(5 5)@2001-01-05' UNION
  SELECT tgeompoint 'Point(7 7)@2001-01-07' )
SELECT asText(appendInstant(inst, NULL, sqrt(2), '1 day' ORDER BY inst)) FROM temp;
/* {[POINT(1 1)@2001-01-01, POINT(2 2)@2001-01-02],
   [POINT(4 4)@2001-01-04, POINT(5 5)@2001-01-05], [POINT(7 7)@2001-01-07]} */
</programlisting>
			</listitem>

			<listitem xml:id="appendSequence">
				<indexterm significance="normal"><primary><varname>appendSequence</varname></primary></indexterm>
				<para>Append a temporal sequence to a temporal value</para>
				<para><varname>appendSequence(ttype,ttypeSeq) → {ttypeSeq,ttypeSeqSet}</varname></para>
				<para><varname>appendSequence(ttypeSeq) → {ttypeSeq,ttypeSeqSet}</varname></para>
				<para>The first version of the function returns the result of appending the second argument to the first one. If either input is NULL, then NULL is returned.</para>
				<para>The second version of the function above is an <emphasis>aggregate</emphasis> function that returns the result of successively appending a set of rows of temporal values. This means that it operates in the same way the <varname>SUM()</varname> and <varname>AVG()</varname> functions do and like most aggregates, it also ignores NULL values.</para>
				<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT appendSequence(tint '1@2001-01-01', tint '{2@2001-01-02, 3@2001-01-03}');
-- {1@2001-01-01, 2@2001-01-02, 3@2001-01-03}
SELECT appendSequence(tint '[1@2001-01-01, 2@2001-01-02]',
  tint '[2@2001-01-02, 3@2001-01-03]');
-- [1@2001-01-01, 2@2001-01-02, 3@2001-01-03]
SELECT asText(appendSequence(tgeompoint '{[Point(1 1 1)@2001-01-01,
  Point(2 2 2)@2001-01-02], [Point(3 3 3)@2001-01-04, Point(3 3 3)@2001-01-05]}',
  tgeompoint '[Point(3 3 3)@2001-01-05, Point(1 1 1)@2001-01-06]'));
/* {[POINT Z (1 1 1)@2001-01-01, POINT Z (2 2 2)@2001-01-02],
   [POINT Z (3 3 3)@2001-01-04, POINT Z (3 3 3)@2001-01-05,
   POINT Z (1 1 1)@2001-01-06]} */
SELECT asText(appendSequence(tgeometry '{[Point(1 1)@2001-01-01, Point(2 2)@2001-01-02], 
  [Linestring(3 3,2 2)@2001-01-04, Point(3 3)@2001-01-05]}',
  tgeometry '[Point(3 3)@2001-01-05, Linestring(3 3,1 1)@2001-01-06]'));
/* {[POINT(1 1)@2001-01-01, POINT(2 2)@2001-01-02], [LINESTRING(3 3,2 2)@2001-01-04, 
     POINT(3 3)@2001-01-05, LINESTRING(3 3,1 1)@2001-01-06]} */
</programlisting>
			</listitem>

			<listitem xml:id="merge">
				<indexterm significance="normal"><primary><varname>merge</varname></primary></indexterm>
				<para>Merge the temporal values</para>
				<para><varname>merge(ttype,ttype) → ttype</varname></para>
				<para><varname>merge(ttype[]) → ttype</varname></para>
				<para><varname>merge(ttype) → ttype</varname></para>
				<para>The temporal values may only intersect at their boundary. In that case, for all temporal types excepted <varname>tgeometry</varname> and <varname>tgeography</varname>, their base values at the common timestamps must be the same, otherwise an error is raised. For the <varname>tgeometry</varname> and <varname>tgeography</varname> types, if the value at their common timestamps is different, the resulting value after the <varname>merge</varname> will be the spatial union of the values. The reason for a different behaviour for these types is that they are the only temporal types that are not <emphasis>scalar</emphasis> types, that is, their value at a given timestamp is not a single element of the domain of the base type, but rather a subset of their domain.</para>
        <para>The third version of the function above is an <emphasis>aggregate</emphasis> function that returns the result of successively appending a set of rows of temporal values. This means that it operates in the same way the <varname>SUM()</varname> and <varname>AVG()</varname> functions do and like most aggregates, it also ignores NULL values.</para>
				<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT merge(tint '1@2001-01-01', tint '1@2001-01-02');
-- {1@2001-01-01, 1@2001-01-02}
SELECT merge(tint '[1@2001-01-01, 2@2001-01-02]', tint '[2@2001-01-02, 1@2001-01-03]');
-- [1@2001-01-01, 2@2001-01-02, 1@2001-01-03]
SELECT merge(tint '[1@2001-01-01, 2@2001-01-02]', tint '[3@2001-01-03, 1@2001-01-04]');
-- {[1@2001-01-01, 2@2001-01-02], [3@2001-01-03, 1@2001-01-04]}
SELECT merge(tint '[1@2001-01-01, 2@2001-01-02]', tint '[1@2001-01-02, 2@2001-01-03]');
-- ERROR:  The temporal values have different value at their common timestamp 2001-01-02
SELECT asText(merge(tgeompoint '{[Point(1 1 1)@2001-01-01,
  Point(2 2 2)@2001-01-02], [Point(3 3 3)@2001-01-04, Point(3 3 3)@2001-01-05]}',
  tgeompoint '{[Point(3 3 3)@2001-01-05, Point(1 1 1)@2001-01-06]}'));
/* {[POINT Z (1 1 1)@2001-01-01, POINT Z (2 2 2)@2001-01-02],
   [POINT Z (3 3 3)@2001-01-04, POINT Z (3 3 3)@2001-01-05,
   POINT Z (1 1 1)@2001-01-06]} */
SELECT asText(merge(tgeometry 'Linestring(1 1,5 1)@2001-01-01',
  tgeometry '{Linestring(5 1,10 1)@2001-01-01, Point(3 3)@2001-01-02}'));
-- {LINESTRING(1 1,5 1,10 1)@2001-01-01, POINT(3 3)@2001-01-02}  
</programlisting>
				<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT merge(ARRAY[tint '1@2001-01-01', '1@2001-01-02']);
-- {1@2001-01-01, 1@2001-01-02}
SELECT merge(ARRAY[tint '{1@2001-01-01, 2@2001-01-02}', '{2@2001-01-02, 3@2001-01-03}']);
-- {1@2001-01-01, 2@2001-01-02, 3@2001-01-03}
SELECT merge(ARRAY[tint '{1@2001-01-01, 2@2001-01-02}', '{3@2001-01-03, 4@2001-01-04}']);
-- {1@2001-01-01, 2@2001-01-02, 3@2001-01-03, 4@2001-01-04}
SELECT merge(ARRAY[tint '[1@2001-01-01, 2@2001-01-02]', '[2@2001-01-02, 1@2001-01-03]']);
-- [1@2001-01-01, 2@2001-01-02, 1@2001-01-03]
SELECT merge(ARRAY[tint '[1@2001-01-01, 2@2001-01-02]', '[3@2001-01-03, 4@2001-01-04]']);
-- {[1@2001-01-01, 2@2001-01-02], [3@2001-01-03, 4@2001-01-04]}
SELECT asText(merge(ARRAY[tgeompoint '{[Point(1 1)@2001-01-01, Point(2 2)@2001-01-02],
  [Point(3 3)@2001-01-03, Point(4 4)@2001-01-04]}', '{[Point(4 4)@2001-01-04,
  Point(3 3)@2001-01-05], [Point(6 6)@2001-01-06, Point(7 7)@2001-01-07]}']));
/* {[Point(1 1)@2001-01-01, Point(2 2)@2001-01-02], [Point(3 3)@2001-01-03,
   Point(4 4)@2001-01-04, Point(3 3)@2001-01-05],
   [Point(6 6)@2001-01-06, Point(7 7)@2001-01-07]} */
SELECT asText(merge(ARRAY[tgeompoint '{[Point(1 1)@2001-01-01, Point(2 2)@2001-01-02]}',
  '{[Point(2 2)@2001-01-02, Point(1 1)@2001-01-03]}']));
-- [Point(1 1)@2001-01-01, Point(2 2)@2001-01-02, Point(1 1)@2001-01-03]
SELECT asText(merge(ARRAY[tgeometry '{[Point(1 1)@2001-01-01, Point(2 2)@2001-01-02]}',
  '{[Linestring(2 2,1 1)@2001-01-02, Point(1 1)@2001-01-03]}']));
-- {[POINT(1 1)@2001-01-01, LINESTRING(2 2,1 1)@2001-01-02, POINT(1 1)@2001-01-03]}
</programlisting>
				<programlisting language="sql" xml:space="preserve" format="linespecific">
WITH temp(inst) AS (
SELECT tfloat '1@2001-01-01' UNION SELECT tfloat '2@2001-01-02' UNION
SELECT tfloat '3@2001-01-03' UNION SELECT tfloat '4@2001-01-04' UNION
SELECT tfloat '5@2001-01-05' )
SELECT merge(inst) FROM temp;
-- {1@2001-01-01, 2@2001-01-02, 3@2001-01-03, 4@2001-01-04, 5@2001-01-05}
</programlisting>
			</listitem>
		</itemizedlist>
	</sect1>

	<sect1 xml:id="ttype_restrictions">
		<title>Restrictions</title>
		<para>There are two complementary sets of restriction functions. The first set functions restricts the temporal value with respect to a value or a time extent. Examples are <varname>atValues</varname> or <varname>atTime</varname>. The second set functions restricts the temporal value with respect to the <emphasis>complement</emphasis> of a value or a time extent. Examples are <varname>minusValues</varname> or <varname>minusTime</varname>.</para>

		<itemizedlist>
			<listitem xml:id="type_atValues">
				<indexterm significance="normal"><primary><varname>atValues</varname></primary></indexterm>
				<indexterm significance="normal"><primary><varname>minusValues</varname></primary></indexterm>
				<para>Restrict to (the complement of) a set of values</para>
				<para><varname>atValues(ttype,values) → ttype</varname></para>
				<para><varname>minusValues(ttype,values) → ttype</varname></para>
				<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT atValues(tint '[1@2001-01-01, 1@2001-01-15)', 1);
-- [1@2001-01-01, 1@2001-01-15)
SELECT atValues(tfloat '[1@2001-01-01, 4@2001-01-4)', floatset '{1, 3, 5}');
-- {[1@2001-01-01], [3@2001-01-03]}
SELECT atValues(tfloat '[1@2001-01-01, 4@2001-01-4)', floatspan '[1,3]');
-- [1@2001-01-01, 3@2001-01-03]
SELECT atValues(tfloat '[1@2001-01-01, 5@2001-01-05)',
  floatspanset '{[1,2], [3,4]}');
-- {[1@2001-01-01, 2@2001-01-02],[3@2001-01-03, 4@2001-01-04]}
SELECT asText(atValues(tgeompoint '[Point(0 0 0)@2001-01-01, Point(2 2 2)@2001-01-03)',
  geometry 'Point(1 1 1)'));
-- {[POINT Z (1 1 1)@2001-01-02]}
SELECT asText(atValues(tgeompoint '[Point(0 0)@2001-01-01, Point(2 2)@2001-01-03)',
  geomset '{"Point(0 0)", "Point(1 1)"}'));
-- {[POINT(0 0)@2001-01-01], [POINT(1 1)@2001-01-02]}
SELECT asText(atValues(tgeometry '[Point(0 0)@2001-01-01, Linestring(0 0,2 2)@2001-01-02, 
  Linestring(0 0,2 2)@2001-01-03]', geometry 'Linestring(0 0,2 2)'));
-- {[LINESTRING(0 0,2 2)@2001-01-02, LINESTRING(0 0,2 2)@2001-01-03]}
</programlisting>
				<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT minusValues(tint '[1@2001-01-01, 2@2001-01-02, 2@2001-01-03)', 1);
-- {[2@2001-01-02, 2@2001-01-03)}
SELECT minusValues(tfloat '[1@2001-01-01, 4@2001-01-4)', floatset '{2, 3}');
/* {[1@2001-01-01, 2@2001-01-02), (2@2001-01-02, 3@2001-01-03),
   (3@2001-01-03, 4@2001-01-04)} */
SELECT minusValues(tfloat '[1@2001-01-01, 4@2001-01-4)', floatspan '[2,3]');
-- {[1@2001-01-01, 2@2001-01-02), (3@2001-01-03, 4@2001-01-04)}
SELECT minusValues(tfloat '[1@2001-01-01, 5@2001-01-05)',
  floatspanset '{[1,2], [3,4]}');
-- {(2@2001-01-02, 3@2001-01-03), (4@2001-01-04, 5@2001-01-05)}
SELECT asText(minusValues(tgeompoint '[Point(0 0 0)@2001-01-01, Point(2 2 2)@2001-01-03)',
  geometry 'Point(1 1 1)'));
/* {[POINT Z (0 0 0)@2001-01-01, POINT Z (1 1 1)@2001-01-02),
   (POINT Z (1 1 1)@2001-01-02, POINT Z (2 2 2)@2001-01-03)} */
SELECT asText(minusValues(tgeompoint '[Point(0 0 0)@2001-01-01, Point(3 3 3)@2001-01-04)',
  geomset '{"Point(1 1 1)', 'Point(2 2 2)"}'));
/* {[POINT Z (0 0 0)@2001-01-01, POINT Z (1 1 1)@2001-01-02),
   (POINT Z (1 1 1)@2001-01-02, POINT Z (2 2 2)@2001-01-03),
  (POINT Z (2 2 2)@2001-01-03, POINT Z (3 3 3)@2001-01-04)} */
SELECT asText(minusValues(tgeometry '[Point(0 0)@2001-01-01, Linestring(0 0,2 2)@2001-01-02, 
  Linestring(0 0,2 2)@2001-01-03]', geometry 'Linestring(0 0,2 2)'));
--  {[POINT(0 0)@2001-01-01, POINT(0 0)@2001-01-02)}
</programlisting>
			</listitem>

			<listitem xml:id="type_atTime">
				<indexterm significance="normal"><primary><varname>atTime</varname></primary></indexterm>
				<indexterm significance="normal"><primary><varname>minusTime</varname></primary></indexterm>
				<para>Restrict to (the complement of) a time value</para>
				<para><varname>atTime(ttype,times) → ttype</varname></para>
				<para><varname>minusTime(ttype,times) → ttype</varname></para>
				<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT atTime(tfloat '[1@2001-01-01, 5@2001-01-05)', timestamptz '2001-01-02');
-- 2@2001-01-02
SELECT atTime(tint '[1@2001-01-01, 1@2001-01-15)',
  tstzset '{2001-01-01, 2001-01-03}');
-- {1@2001-01-01, 1@2001-01-03}
SELECT atTime(tfloat '{[1@2001-01-01, 3@2001-01-03), [3@2001-01-04, 1@2001-01-06)}',
  tstzspan '[2001-01-02,2001-01-05)');
-- {[2@2001-01-02, 3@2001-01-03), [3@2001-01-04, 2@2001-01-05)}
SELECT atTime(tint '[1@2001-01-01, 1@2001-01-15)',
  tstzspanset '{[2001-01-01, 2001-01-03), [2001-01-04, 2001-01-05)}');
-- {[1@2001-01-01, 1@2001-01-03),[1@2001-01-04, 1@2001-01-05)}
</programlisting>
				<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT minusTime(tfloat '[1@2001-01-01, 5@2001-01-05)', timestamptz '2001-01-02');
-- {[1@2001-01-01, 2@2001-01-02), (2@2001-01-02, 5@2001-01-05)}
SELECT minusTime(tint '[1@2001-01-01, 1@2001-01-15)',
  tstzset '{2001-01-02, 2001-01-03}');
/* {[1@2001-01-01, 1@2001-01-02), (1@2001-01-02, 1@2001-01-03),
   (1@2001-01-03, 1@2001-01-15)} */
SELECT minusTime(tfloat '{[1@2001-01-01, 3@2001-01-03), [3@2001-01-04, 1@2001-01-06)}',
  tstzspan '[2001-01-02,2001-01-05)');
-- {[1@2001-01-01, 2@2001-01-02), [2@2001-01-05, 1@2001-01-06)}
SELECT minusTime(tint '[1@2001-01-01, 1@2001-01-15)',
  tstzspanset '{[2001-01-02, 2001-01-03), [2001-01-04, 2001-01-05)}');
/* {[1@2001-01-01, 1@2001-01-02), [1@2001-01-03, 1@2001-01-04),
   [1@2001-01-05, 1@2001-01-15)} */
</programlisting>
			</listitem>
		</itemizedlist>
	</sect1>

	<sect1 xml:id="ttype_bbox">
		<title>Bounding Box Operators</title>

		<para>These operators test whether the bounding boxes of their arguments satisfy the predicate and result in a Boolean value. As stated in <xref linkend="ttype_p1"/>, the bounding box associated to a temporal type depends on the base type: It is the <varname>tstzspan</varname> type for the <varname>tbool</varname> and <varname>ttext</varname> types, the <varname>tbox</varname> type for the <varname>tint</varname> and <varname>tfloat</varname> types, and the <varname>stbox</varname> type for the <varname>tgeompoint</varname> and <varname>tgeogpoint</varname> types. Furthermore, as seen in <xref linkend="box_conversions"/>, many PostgreSQL, PostGIS, or MobilityDB types can be converted to the <varname>tbox</varname> and <varname>stbox</varname> types. For example, numeric and span types can be converted to type <varname>tbox</varname>, types <varname>geometry</varname> and <varname>geography</varname> can be converted to type <varname>stbox</varname>, and time types and temporal types can be converted to types <varname>tbox</varname> and <varname>stbox</varname>.</para>

		<para>A first set of operators consider the topological relationships between the bounding boxes. There are five topological operators: overlaps (<varname>&amp;&amp;</varname>), contains (<varname>@&gt;</varname>), contained (<varname>&lt;@</varname>), same (<varname>~=</varname>), and adjacent (<varname>-|-</varname>). The arguments of these operators can be a base type, a box, or a temporal type and the operators verify the topological relationship taking into account the value and/or the time dimension depending on the type of the arguments.</para>

		<para>Another set of operators consider the relative position of the bounding boxes. The operators <varname>&lt;&lt;</varname>, <varname>&gt;&gt;</varname>, <varname>&amp;&lt;</varname>, and <varname>&amp;&gt;</varname> consider the value dimension for <varname>tint</varname> and <varname>tfloat</varname> types and the X coordinates for the <varname>tgeompoint</varname> and <varname>tgeogpoint</varname> types, the operators <varname>&lt;&lt;|</varname>, <varname>|&gt;&gt;</varname>, <varname>&amp;&lt;|</varname>, and <varname>|&amp;&gt;</varname> consider the Y coordinates for the <varname>tgeompoint</varname> and <varname>tgeogpoint</varname> types, the operators <varname>&lt;&lt;/</varname>, <varname>/&gt;&gt;</varname>, <varname>&amp;&lt;/</varname>, and <varname>/&amp;&gt;</varname> consider the Z coordinates for the <varname>tgeompoint</varname> and <varname>tgeogpoint</varname> types, and the operators <varname>&lt;&lt;#</varname>, <varname>#&gt;&gt;</varname>, <varname>#&amp;&lt;</varname>, and <varname>#&amp;&gt;</varname> consider the time dimension for all temporal types.</para>

		<para>Finally, it is worth noting that the bounding box operators allow to mix 2D/3D geometries but in that case, the computation is only performed on 2D.</para>

		<para>We refer to <xref linkend="box_topo_pos"/> for the bounding box operators.</para>
	</sect1>

	<sect1 xml:id="ttype_comparisons">
		<title>Comparisons</title>

		<sect2>
			<title>Traditional Comparisons</title>

			<para>The traditional comparison operators (<varname>=</varname>, <varname>&lt;</varname>, and so on) require that the left and right operands be of the same base type. Excepted equality  and inequality, the other comparison operators are not useful in the real world but allow B-tree indexes to be constructed on temporal types. These operators compare the bounding periods (see <xref linkend="setspan_comparisons"/>), then the bounding boxes (see <xref linkend="box_comparisons"/>) and if those are equal, then the comparison depends on the subtype. For instant values, they compare first the timestamps and if those are equal, compare the values. For sequence values, they compare the first N instants, where N is the minimum of the number of composing instants of both values. Finally, for sequence set values, they compare the first N sequence values, where N is the minimum of the number of composing sequences of both values.</para>

			<para>The equality and inequality operators consider the equivalent representation for different subtypes as shown next.
				<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT tint '1@2001-01-01' = tint '{1@2001-01-01}';
-- true
SELECT tfloat '1.5@2001-01-01' = tfloat '[1.5@2001-01-01]';
-- true
SELECT ttext 'AAA@2001-01-01' = ttext '{[AAA@2001-01-01]}';
-- true
SELECT tgeompoint '{Point(1 1)@2001-01-01, Point(2 2)@2001-01-02}' =
  tgeompoint '{[Point(1 1)@2001-01-01], [Point(2 2)@2001-01-02]}';
-- true
SELECT tgeography '[Point(1 1)@2001-01-01, Linestring(1 1,2 2)@2001-01-02]' =
  tgeography '{[Point(1 1)@2001-01-01, Linestring(1 1,2 2)@2001-01-02]}';
-- true
</programlisting>
			</para>

			<itemizedlist>
				<listitem xml:id="ttype_eq">
					<indexterm significance="normal"><primary><varname>=</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>&lt;&gt;</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>&lt;</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>&gt;</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>&lt;=</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>&gt;=</varname></primary></indexterm>
					<para>Traditional comparisons</para>
					<para><varname>ttype {=, &lt;&gt;, &lt;, &gt;, &lt;=, &gt;=} ttype → boolean</varname></para>
					<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT tint '[1@2001-01-01, 1@2001-01-04)' = tint '[2@2001-01-03, 2@2001-01-05)';
-- false
SELECT tint '[1@2001-01-01, 1@2001-01-04)' &lt;&gt; tint '[2@2001-01-03, 2@2001-01-05)';
-- true
SELECT tint '[1@2001-01-01, 1@2001-01-04)' &lt; tint '[2@2001-01-03, 2@2001-01-05)';
-- true
SELECT tint '[1@2001-01-01, 1@2001-01-04)' &gt; tint '[2@2001-01-03, 2@2001-01-05)';
-- false
SELECT tint '[1@2001-01-01, 1@2001-01-04)' &lt;= tint '[2@2001-01-03, 2@2001-01-05)';
-- true
SELECT tint '[1@2001-01-01, 1@2001-01-04)' &gt;= tint '[2@2001-01-03, 2@2001-01-05)';
-- false
</programlisting>
				</listitem>
			</itemizedlist>
		</sect2>

		<sect2 xml:id="ever_always_comparison">
			<title>Ever and Always Comparisons</title>
			<para>
				A possible generalization of the traditional comparison operators (<varname>=</varname>, <varname>&lt;&gt;</varname>, <varname>&lt;</varname>, <varname>&lt;=</varname>, etc.) to temporal types consists in determining whether the comparison is ever or always true. In this case, the result is a Boolean value. MobilityDB provides operators to test whether the comparison of a temporal value and a value of the base type or two temporal values is ever or always true. These operators are denoted by prefixing the traditional comparison operators with, respectively, <varname>?</varname> (ever) and <varname>%</varname> (always). Some examples are <varname>?=</varname>, <varname>%&lt;&gt;</varname>, or <varname>?&lt;=</varname>. Ever and always equality and non-equality are available for all temporal types, while ever and always inequalities are only available for temporal types whose base type has a total order defined, that is, <varname>tint</varname>, <varname>tfloat</varname>, or <varname>ttext</varname>. The ever and always comparisons are inverse operators: for example, <varname>?=</varname> is the inverse of <varname>%&lt;&gt;</varname>, and <varname>?&gt;</varname> is the inverse of <varname>%&lt;=</varname>.
			</para>
			<itemizedlist>
				<listitem xml:id="ttype_eveq">
					<indexterm significance="normal"><primary><varname>?=</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>%=</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>?&lt;&gt;</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>%&lt;&gt;</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>?&lt;</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>%&lt;</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>?&gt;</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>%&gt;</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>?&lt;=</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>%&lt;=</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>?&gt;=</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>%&gt;=</varname></primary></indexterm>
					<para>Ever and always comparisons</para>
					<para><varname>{base,ttype} {?=, ?&lt;&gt;, ?&lt;, ?&gt;, ?&lt;=, ?&gt;=} {base,ttype} → boolean</varname></para>
					<para><varname>{base,ttype} {%=, %&lt;&gt;, %&lt;, %&gt;, %&lt;=, %&gt;=} {base,ttype} → boolean</varname></para>
					<para>The operators do not take into account whether the bounds are inclusive or not.</para>
					<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT tint '[1@2001-01-01, 3@2001-01-04]' ?= 2;
-- false
SELECT tgeometry '[Point(0 0)@2001-01-01, Linestring(0 0,1 1)@2001-01-04]' ?=
  geometry 'Linestring(1 1,0 0)';
-- true
SELECT tfloat '[1@2001-01-01, 1@2001-01-04)' %= 1;
-- true
SELECT tgeometry '[Linestring(0 0,1 1)@2001-01-01, Linestring(1 1,0 0)@2001-01-04)' %=
  geometry 'Linestring(0 0,1 1)';
-- true
</programlisting>
					<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT tfloat '[1@2001-01-01, 3@2001-01-04)' ?&lt;&gt; 2;
-- true
SELECT tgeompoint '[Point(1 1)@2001-01-01, Point(1 1)@2001-01-04)' ?&lt;&gt;
  geometry 'Point(1 1)';
-- false
SELECT tfloat '[1@2001-01-01, 3@2001-01-04)' %&lt;&gt; 2;
-- false
SELECT tgeogpoint '[Point(1 1)@2001-01-01, Point(1 1)@2001-01-04)' %&lt;&gt;
  geography 'Point(2 2)';
-- true
</programlisting>
					<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT tint '[1@2001-01-01, 4@2001-01-04]' ?&lt; 2;
-- true
SELECT tfloat '[1@2001-01-01, 4@2001-01-04)' %&lt; 2;
-- false
</programlisting>
					<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT tint '[1@2001-01-03, 1@2001-01-05]' ?&gt; 0;
-- true
SELECT tfloat '[1@2001-01-03, 1@2001-01-05)' %&gt; 1;
-- false
</programlisting>
					<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT tint '[1@2001-01-01, 1@2001-01-05]' ?&lt;= 2;
-- true
SELECT tfloat '[1@2001-01-01, 1@2001-01-05)' %&lt;= 4;
-- true
</programlisting>
					<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT ttext '{[AAA@2001-01-01, AAA@2001-01-03), [BBB@2001-01-04, BBB@2001-01-05)}'
   ?&gt; 'AAA'::text;
-- true
SELECT ttext '{[AAA@2001-01-01, AAA@2001-01-03), [BBB@2001-01-04, BBB@2001-01-05)}'
   %&gt; 'AAA'::text;
-- false
</programlisting>
				</listitem>
			</itemizedlist>
		</sect2>

		<sect2>
			<title>Temporal Comparisons</title>
			<para>Another possible generalization of the traditional comparison operators (<varname>=</varname>, <varname>&lt;&gt;</varname>, <varname>&lt;</varname>, <varname>&lt;=</varname>,  etc.) to temporal types consists in determining whether the comparison is true or false at each instant. In this case, the result is a temporal Boolean. The temporal comparison operators are denoted by prefixing the traditional comparison operators with <varname>#</varname>. Some examples are <varname>#=</varname> or <varname>#&lt;=</varname>. Temporal equality and non-equality are available for all temporal types, while temporal inequalities are only available for temporal types whose base type has a total order defined, that is, <varname>tint</varname>, <varname>tfloat</varname>, or <varname>ttext</varname>.</para>

			<itemizedlist>
				<listitem xml:id="ttype_teq">
					<indexterm significance="normal"><primary><varname>#=</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>#&lt;&gt;</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>#&lt;</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>#&gt;</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>#&lt;=</varname></primary></indexterm>
					<indexterm significance="normal"><primary><varname>#&gt;=</varname></primary></indexterm>
					<para>Temporal comparisons</para>
					<para><varname>{base,ttype} {#=, #&lt;&gt;, #&lt;, #&gt;, #&lt;=, #&gt;=} {base,ttype} → boolean</varname></para>
					<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT tfloat '[1@2001-01-01, 2@2001-01-04)' #= 3;
-- {[f@2001-01-01, f@2001-01-04)}
SELECT tfloat '[1@2001-01-01, 4@2001-01-04)' #= tfloat '[4@2001-01-02, 1@2001-01-05)';
-- {[f@2001-01-02, t@2001-01-03], (f@2001-01-03, f@2001-01-04)}
SELECT tgeompoint '[Point(0 0)@2001-01-01, Point(2 2)@2001-01-03)' #=
  geometry 'Point(1 1)';
-- {[f@2001-01-01, t@2001-01-02], (f@2001-01-02, f@2001-01-03)}
SELECT tgeometry '[Point(0 0)@2001-01-01, Linestring(1 1,2 2)@2001-01-03]' #=
  geometry 'Linestring(2 2,1 1)';
-- {[f@2001-01-01, t@2001-01-03]}
</programlisting>
					<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT tfloat '[1@2001-01-01, 4@2001-01-04)' #&lt;&gt; 2;
-- {[t@2001-01-01, f@2001-01-02], (t@2001-01-02, 2001-01-04)}
SELECT tfloat '[1@2001-01-01, 4@2001-01-04)' #&lt;&gt; tfloat '[2@2001-01-02, 2@2001-01-05)';
-- {[f@2001-01-02], (t@2001-01-02, t@2001-01-04)}
SELECT tgeometry '[Point(0 0)@2001-01-01, Linestring(1 1,2 2)@2001-01-03]' #&lt;&gt;
  geometry 'Linestring(2 2,1 1)';
-- {[t@2001-01-01, f@2001-01-03]}
</programlisting>
					<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT tfloat '[1@2001-01-01, 4@2001-01-04)' #&lt; 2;
-- {[t@2001-01-01, f@2001-01-02, f@2001-01-04)}
SELECT 1 #&gt; tint '[1@2001-01-03, 1@2001-01-05)';
-- [f@2001-01-03, f@2001-01-05)
SELECT tfloat '[1@2001-01-01, 1@2001-01-05)' #&lt;= tfloat '{2@2001-01-03, 3@2001-01-04}';
-- {t@2001-01-03, t@2001-01-04}
SELECT 'AAA'::text #&gt; ttext '{[AAA@2001-01-01, AAA@2001-01-03),
  [BBB@2001-01-04, BBB@2001-01-05)}';
-- {[f@2001-01-01, f@2001-01-03), [t@2001-01-04, t@2001-01-05)}
</programlisting>
				</listitem>
			</itemizedlist>
		</sect2>
	</sect1>

	<sect1 xml:id="ttype_miscellaneous">
		<title>Miscellaneous</title>
		<itemizedlist>
			<listitem xml:id="mobilitydb_version">
				<indexterm significance="normal"><primary><varname>mobilitydb_version</varname></primary></indexterm>
				<para>Version of the MobilityDB extension</para>
				<para><varname>mobilitydb_version() → text</varname></para>
				<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT mobilitydb_version();
-- MobilityDB 1.3.0
</programlisting>
			</listitem>

			<listitem xml:id="mobilitydb_full_version">
				<indexterm significance="normal"><primary><varname>mobilitydb_full_version</varname></primary></indexterm>
				<para>Versions of the MobilityDB extension and its dependencies</para>
				<para><varname>mobilitydb_full_version() → text</varname></para>
				<programlisting language="sql" xml:space="preserve" format="linespecific">
SELECT mobilitydb_full_version();
/* MobilityDB 1.3.0, PostgreSQL 17.2, PostGIS 3.5.2, GEOS 3.12.0-CAPI-1.18.0, PROJ 9.2.0,
   JSON-C 0.13.1, GSL 2.5 */
</programlisting>
			</listitem>
		</itemizedlist>
	</sect1>

</chapter>