PostgreSQL Source Code git master
seg.c
Go to the documentation of this file.
1/*
2 * contrib/seg/seg.c
3 *
4 ******************************************************************************
5 This file contains routines that can be bound to a Postgres backend and
6 called by the backend in the process of processing queries. The calling
7 format for these routines is dictated by Postgres architecture.
8******************************************************************************/
9
10#include "postgres.h"
11
12#include <float.h>
13#include <math.h>
14
15#include "access/gist.h"
16#include "access/stratnum.h"
17#include "fmgr.h"
18
19#include "segdata.h"
20
21
22#define DatumGetSegP(X) ((SEG *) DatumGetPointer(X))
23#define PG_GETARG_SEG_P(n) DatumGetSegP(PG_GETARG_DATUM(n))
24
25
26/*
27#define GIST_DEBUG
28#define GIST_QUERY_DEBUG
29*/
30
32
33/*
34 * Auxiliary data structure for picksplit method.
35 */
36typedef struct
37{
38 float center;
42
43/*
44** Input/Output routines
45*/
52
53/*
54** GiST support methods
55*/
65static Datum gseg_binary_union(Datum r1, Datum r2, int *sizep);
66
67
68/*
69** R-tree support functions
70*/
81static void rt_seg_size(SEG *a, float *size);
82
83/*
84** Various operators
85*/
92
93/*
94** Auxiliary functions
95*/
96static int restore(char *result, float val, int n);
97
98
99/*****************************************************************************
100 * Input/Output functions
101 *****************************************************************************/
102
103Datum
105{
106 char *str = PG_GETARG_CSTRING(0);
107 SEG *result = palloc(sizeof(SEG));
108 yyscan_t scanner;
109
110 seg_scanner_init(str, &scanner);
111
112 if (seg_yyparse(result, fcinfo->context, scanner) != 0)
113 seg_yyerror(result, fcinfo->context, scanner, "bogus input");
114
115 seg_scanner_finish(scanner);
116
117 PG_RETURN_POINTER(result);
118}
119
120Datum
122{
123 SEG *seg = PG_GETARG_SEG_P(0);
124 char *result;
125 char *p;
126
127 p = result = (char *) palloc(40);
128
129 if (seg->l_ext == '>' || seg->l_ext == '<' || seg->l_ext == '~')
130 p += sprintf(p, "%c", seg->l_ext);
131
132 if (seg->lower == seg->upper && seg->l_ext == seg->u_ext)
133 {
134 /*
135 * indicates that this interval was built by seg_in off a single point
136 */
137 p += restore(p, seg->lower, seg->l_sigd);
138 }
139 else
140 {
141 if (seg->l_ext != '-')
142 {
143 /* print the lower boundary if exists */
144 p += restore(p, seg->lower, seg->l_sigd);
145 p += sprintf(p, " ");
146 }
147 p += sprintf(p, "..");
148 if (seg->u_ext != '-')
149 {
150 /* print the upper boundary if exists */
151 p += sprintf(p, " ");
152 if (seg->u_ext == '>' || seg->u_ext == '<' || seg->l_ext == '~')
153 p += sprintf(p, "%c", seg->u_ext);
154 p += restore(p, seg->upper, seg->u_sigd);
155 }
156 }
157
158 PG_RETURN_CSTRING(result);
159}
160
161Datum
163{
164 SEG *seg = PG_GETARG_SEG_P(0);
165
166 PG_RETURN_FLOAT4(((float) seg->lower + (float) seg->upper) / 2.0);
167}
168
169Datum
171{
172 SEG *seg = PG_GETARG_SEG_P(0);
173
175}
176
177Datum
179{
180 SEG *seg = PG_GETARG_SEG_P(0);
181
183}
184
185
186/*****************************************************************************
187 * GiST functions
188 *****************************************************************************/
189
190/*
191** The GiST Consistent method for segments
192** Should return false if for all data items x below entry,
193** the predicate x op query == false, where op is the oper
194** corresponding to strategy in the pg_amop table.
195*/
196Datum
198{
199 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
200 Datum query = PG_GETARG_DATUM(1);
202
203 /* Oid subtype = PG_GETARG_OID(3); */
204 bool *recheck = (bool *) PG_GETARG_POINTER(4);
205
206 /* All cases served by this function are exact */
207 *recheck = false;
208
209 /*
210 * if entry is not leaf, use gseg_internal_consistent, else use
211 * gseg_leaf_consistent
212 */
213 if (GIST_LEAF(entry))
214 return gseg_leaf_consistent(entry->key, query, strategy);
215 else
216 return gseg_internal_consistent(entry->key, query, strategy);
217}
218
219/*
220** The GiST Union method for segments
221** returns the minimal bounding seg that encloses all the entries in entryvec
222*/
223Datum
225{
227 int *sizep = (int *) PG_GETARG_POINTER(1);
228 int numranges,
229 i;
230 Datum out = 0;
231 Datum tmp;
232
233#ifdef GIST_DEBUG
234 fprintf(stderr, "union\n");
235#endif
236
237 numranges = entryvec->n;
238 tmp = entryvec->vector[0].key;
239 *sizep = sizeof(SEG);
240
241 for (i = 1; i < numranges; i++)
242 {
243 out = gseg_binary_union(tmp, entryvec->vector[i].key, sizep);
244 tmp = out;
245 }
246
247 PG_RETURN_DATUM(out);
248}
249
250/*
251** GiST Compress and Decompress methods for segments
252** do not do anything.
253*/
254Datum
256{
258}
259
260Datum
262{
264}
265
266/*
267** The GiST Penalty method for segments
268** As in the R-tree paper, we use change in area as our penalty metric
269*/
270Datum
272{
273 GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
274 GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
275 float *result = (float *) PG_GETARG_POINTER(2);
276 SEG *ud;
277 float tmp1,
278 tmp2;
279
281 origentry->key,
282 newentry->key));
283 rt_seg_size(ud, &tmp1);
284 rt_seg_size(DatumGetSegP(origentry->key), &tmp2);
285 *result = tmp1 - tmp2;
286
287#ifdef GIST_DEBUG
288 fprintf(stderr, "penalty\n");
289 fprintf(stderr, "\t%g\n", *result);
290#endif
291
292 PG_RETURN_POINTER(result);
293}
294
295/*
296 * Compare function for gseg_picksplit_item: sort by center.
297 */
298static int
299gseg_picksplit_item_cmp(const void *a, const void *b)
300{
301 const gseg_picksplit_item *i1 = (const gseg_picksplit_item *) a;
302 const gseg_picksplit_item *i2 = (const gseg_picksplit_item *) b;
303
304 if (i1->center < i2->center)
305 return -1;
306 else if (i1->center == i2->center)
307 return 0;
308 else
309 return 1;
310}
311
312/*
313 * The GiST PickSplit method for segments
314 *
315 * We used to use Guttman's split algorithm here, but since the data is 1-D
316 * it's easier and more robust to just sort the segments by center-point and
317 * split at the middle.
318 */
319Datum
321{
324 int i;
325 SEG *seg,
326 *seg_l,
327 *seg_r;
328 gseg_picksplit_item *sort_items;
329 OffsetNumber *left,
330 *right;
331 OffsetNumber maxoff;
332 OffsetNumber firstright;
333
334#ifdef GIST_DEBUG
335 fprintf(stderr, "picksplit\n");
336#endif
337
338 /* Valid items in entryvec->vector[] are indexed 1..maxoff */
339 maxoff = entryvec->n - 1;
340
341 /*
342 * Prepare the auxiliary array and sort it.
343 */
344 sort_items = (gseg_picksplit_item *)
345 palloc(maxoff * sizeof(gseg_picksplit_item));
346 for (i = 1; i <= maxoff; i++)
347 {
348 seg = DatumGetSegP(entryvec->vector[i].key);
349 /* center calculation is done this way to avoid possible overflow */
350 sort_items[i - 1].center = seg->lower * 0.5f + seg->upper * 0.5f;
351 sort_items[i - 1].index = i;
352 sort_items[i - 1].data = seg;
353 }
354 qsort(sort_items, maxoff, sizeof(gseg_picksplit_item),
356
357 /* sort items below "firstright" will go into the left side */
358 firstright = maxoff / 2;
359
360 v->spl_left = (OffsetNumber *) palloc(maxoff * sizeof(OffsetNumber));
361 v->spl_right = (OffsetNumber *) palloc(maxoff * sizeof(OffsetNumber));
362 left = v->spl_left;
363 v->spl_nleft = 0;
364 right = v->spl_right;
365 v->spl_nright = 0;
366
367 /*
368 * Emit segments to the left output page, and compute its bounding box.
369 */
370 seg_l = (SEG *) palloc(sizeof(SEG));
371 memcpy(seg_l, sort_items[0].data, sizeof(SEG));
372 *left++ = sort_items[0].index;
373 v->spl_nleft++;
374 for (i = 1; i < firstright; i++)
375 {
376 Datum sortitem = PointerGetDatum(sort_items[i].data);
377
379 PointerGetDatum(seg_l),
380 sortitem));
381 *left++ = sort_items[i].index;
382 v->spl_nleft++;
383 }
384
385 /*
386 * Likewise for the right page.
387 */
388 seg_r = (SEG *) palloc(sizeof(SEG));
389 memcpy(seg_r, sort_items[firstright].data, sizeof(SEG));
390 *right++ = sort_items[firstright].index;
391 v->spl_nright++;
392 for (i = firstright + 1; i < maxoff; i++)
393 {
394 Datum sortitem = PointerGetDatum(sort_items[i].data);
395
397 PointerGetDatum(seg_r),
398 sortitem));
399 *right++ = sort_items[i].index;
400 v->spl_nright++;
401 }
402
403 v->spl_ldatum = PointerGetDatum(seg_l);
404 v->spl_rdatum = PointerGetDatum(seg_r);
405
407}
408
409/*
410** Equality methods
411*/
412Datum
414{
415 bool *result = (bool *) PG_GETARG_POINTER(2);
416
418 *result = true;
419 else
420 *result = false;
421
422#ifdef GIST_DEBUG
423 fprintf(stderr, "same: %s\n", (*result ? "TRUE" : "FALSE"));
424#endif
425
426 PG_RETURN_POINTER(result);
427}
428
429/*
430** SUPPORT ROUTINES
431*/
432static Datum
434{
435 Datum retval;
436
437#ifdef GIST_QUERY_DEBUG
438 fprintf(stderr, "leaf_consistent, %d\n", strategy);
439#endif
440
441 switch (strategy)
442 {
444 retval = DirectFunctionCall2(seg_left, key, query);
445 break;
447 retval = DirectFunctionCall2(seg_over_left, key, query);
448 break;
450 retval = DirectFunctionCall2(seg_overlap, key, query);
451 break;
453 retval = DirectFunctionCall2(seg_over_right, key, query);
454 break;
456 retval = DirectFunctionCall2(seg_right, key, query);
457 break;
459 retval = DirectFunctionCall2(seg_same, key, query);
460 break;
463 retval = DirectFunctionCall2(seg_contains, key, query);
464 break;
467 retval = DirectFunctionCall2(seg_contained, key, query);
468 break;
469 default:
470 retval = false;
471 }
472
473 PG_RETURN_DATUM(retval);
474}
475
476static Datum
478{
479 bool retval;
480
481#ifdef GIST_QUERY_DEBUG
482 fprintf(stderr, "internal_consistent, %d\n", strategy);
483#endif
484
485 switch (strategy)
486 {
488 retval =
490 break;
492 retval =
494 break;
496 retval =
498 break;
500 retval =
502 break;
504 retval =
506 break;
510 retval =
512 break;
515 retval =
517 break;
518 default:
519 retval = false;
520 }
521
522 PG_RETURN_BOOL(retval);
523}
524
525static Datum
526gseg_binary_union(Datum r1, Datum r2, int *sizep)
527{
528 Datum retval;
529
530 retval = DirectFunctionCall2(seg_union, r1, r2);
531 *sizep = sizeof(SEG);
532
533 return retval;
534}
535
536
537Datum
539{
540 SEG *a = PG_GETARG_SEG_P(0);
541 SEG *b = PG_GETARG_SEG_P(1);
542
543 PG_RETURN_BOOL((a->lower <= b->lower) && (a->upper >= b->upper));
544}
545
546Datum
548{
551
553}
554
555/*****************************************************************************
556 * Operator class for R-tree indexing
557 *****************************************************************************/
558
559Datum
561{
564 PG_GETARG_DATUM(1)));
565
566 PG_RETURN_BOOL(cmp == 0);
567}
568
569/* seg_overlap -- does a overlap b?
570 */
571Datum
573{
574 SEG *a = PG_GETARG_SEG_P(0);
575 SEG *b = PG_GETARG_SEG_P(1);
576
577 PG_RETURN_BOOL(((a->upper >= b->upper) && (a->lower <= b->upper)) ||
578 ((b->upper >= a->upper) && (b->lower <= a->upper)));
579}
580
581/* seg_over_left -- is the right edge of (a) located at or left of the right edge of (b)?
582 */
583Datum
585{
586 SEG *a = PG_GETARG_SEG_P(0);
587 SEG *b = PG_GETARG_SEG_P(1);
588
589 PG_RETURN_BOOL(a->upper <= b->upper);
590}
591
592/* seg_left -- is (a) entirely on the left of (b)?
593 */
594Datum
596{
597 SEG *a = PG_GETARG_SEG_P(0);
598 SEG *b = PG_GETARG_SEG_P(1);
599
600 PG_RETURN_BOOL(a->upper < b->lower);
601}
602
603/* seg_right -- is (a) entirely on the right of (b)?
604 */
605Datum
607{
608 SEG *a = PG_GETARG_SEG_P(0);
609 SEG *b = PG_GETARG_SEG_P(1);
610
611 PG_RETURN_BOOL(a->lower > b->upper);
612}
613
614/* seg_over_right -- is the left edge of (a) located at or right of the left edge of (b)?
615 */
616Datum
618{
619 SEG *a = PG_GETARG_SEG_P(0);
620 SEG *b = PG_GETARG_SEG_P(1);
621
622 PG_RETURN_BOOL(a->lower >= b->lower);
623}
624
625Datum
627{
628 SEG *a = PG_GETARG_SEG_P(0);
629 SEG *b = PG_GETARG_SEG_P(1);
630 SEG *n;
631
632 n = (SEG *) palloc(sizeof(*n));
633
634 /* take max of upper endpoints */
635 if (a->upper > b->upper)
636 {
637 n->upper = a->upper;
638 n->u_sigd = a->u_sigd;
639 n->u_ext = a->u_ext;
640 }
641 else
642 {
643 n->upper = b->upper;
644 n->u_sigd = b->u_sigd;
645 n->u_ext = b->u_ext;
646 }
647
648 /* take min of lower endpoints */
649 if (a->lower < b->lower)
650 {
651 n->lower = a->lower;
652 n->l_sigd = a->l_sigd;
653 n->l_ext = a->l_ext;
654 }
655 else
656 {
657 n->lower = b->lower;
658 n->l_sigd = b->l_sigd;
659 n->l_ext = b->l_ext;
660 }
661
663}
664
665Datum
667{
668 SEG *a = PG_GETARG_SEG_P(0);
669 SEG *b = PG_GETARG_SEG_P(1);
670 SEG *n;
671
672 n = (SEG *) palloc(sizeof(*n));
673
674 /* take min of upper endpoints */
675 if (a->upper < b->upper)
676 {
677 n->upper = a->upper;
678 n->u_sigd = a->u_sigd;
679 n->u_ext = a->u_ext;
680 }
681 else
682 {
683 n->upper = b->upper;
684 n->u_sigd = b->u_sigd;
685 n->u_ext = b->u_ext;
686 }
687
688 /* take max of lower endpoints */
689 if (a->lower > b->lower)
690 {
691 n->lower = a->lower;
692 n->l_sigd = a->l_sigd;
693 n->l_ext = a->l_ext;
694 }
695 else
696 {
697 n->lower = b->lower;
698 n->l_sigd = b->l_sigd;
699 n->l_ext = b->l_ext;
700 }
701
703}
704
705static void
707{
708 if (a == (SEG *) NULL || a->upper <= a->lower)
709 *size = 0.0;
710 else
711 *size = fabsf(a->upper - a->lower);
712}
713
714Datum
716{
717 SEG *seg = PG_GETARG_SEG_P(0);
718
719 PG_RETURN_FLOAT4(fabsf(seg->upper - seg->lower));
720}
721
722
723/*****************************************************************************
724 * Miscellaneous operators
725 *****************************************************************************/
726Datum
728{
729 SEG *a = PG_GETARG_SEG_P(0);
730 SEG *b = PG_GETARG_SEG_P(1);
731
732 /*
733 * First compare on lower boundary position
734 */
735 if (a->lower < b->lower)
736 PG_RETURN_INT32(-1);
737 if (a->lower > b->lower)
739
740 /*
741 * a->lower == b->lower, so consider type of boundary.
742 *
743 * A '-' lower bound is < any other kind (this could only be relevant if
744 * -HUGE_VAL is used as a regular data value). A '<' lower bound is < any
745 * other kind except '-'. A '>' lower bound is > any other kind.
746 */
747 if (a->l_ext != b->l_ext)
748 {
749 if (a->l_ext == '-')
750 PG_RETURN_INT32(-1);
751 if (b->l_ext == '-')
753 if (a->l_ext == '<')
754 PG_RETURN_INT32(-1);
755 if (b->l_ext == '<')
757 if (a->l_ext == '>')
759 if (b->l_ext == '>')
760 PG_RETURN_INT32(-1);
761 }
762
763 /*
764 * For other boundary types, consider # of significant digits first.
765 */
766 if (a->l_sigd < b->l_sigd) /* (a) is blurred and is likely to include (b) */
767 PG_RETURN_INT32(-1);
768 if (a->l_sigd > b->l_sigd) /* (a) is less blurred and is likely to be
769 * included in (b) */
771
772 /*
773 * For same # of digits, an approximate boundary is more blurred than
774 * exact.
775 */
776 if (a->l_ext != b->l_ext)
777 {
778 if (a->l_ext == '~') /* (a) is approximate, while (b) is exact */
779 PG_RETURN_INT32(-1);
780 if (b->l_ext == '~')
782 /* can't get here unless data is corrupt */
783 elog(ERROR, "bogus lower boundary types %d %d",
784 (int) a->l_ext, (int) b->l_ext);
785 }
786
787 /* at this point, the lower boundaries are identical */
788
789 /*
790 * First compare on upper boundary position
791 */
792 if (a->upper < b->upper)
793 PG_RETURN_INT32(-1);
794 if (a->upper > b->upper)
796
797 /*
798 * a->upper == b->upper, so consider type of boundary.
799 *
800 * A '-' upper bound is > any other kind (this could only be relevant if
801 * HUGE_VAL is used as a regular data value). A '<' upper bound is < any
802 * other kind. A '>' upper bound is > any other kind except '-'.
803 */
804 if (a->u_ext != b->u_ext)
805 {
806 if (a->u_ext == '-')
808 if (b->u_ext == '-')
809 PG_RETURN_INT32(-1);
810 if (a->u_ext == '<')
811 PG_RETURN_INT32(-1);
812 if (b->u_ext == '<')
814 if (a->u_ext == '>')
816 if (b->u_ext == '>')
817 PG_RETURN_INT32(-1);
818 }
819
820 /*
821 * For other boundary types, consider # of significant digits first. Note
822 * result here is converse of the lower-boundary case.
823 */
824 if (a->u_sigd < b->u_sigd) /* (a) is blurred and is likely to include (b) */
826 if (a->u_sigd > b->u_sigd) /* (a) is less blurred and is likely to be
827 * included in (b) */
828 PG_RETURN_INT32(-1);
829
830 /*
831 * For same # of digits, an approximate boundary is more blurred than
832 * exact. Again, result is converse of lower-boundary case.
833 */
834 if (a->u_ext != b->u_ext)
835 {
836 if (a->u_ext == '~') /* (a) is approximate, while (b) is exact */
838 if (b->u_ext == '~')
839 PG_RETURN_INT32(-1);
840 /* can't get here unless data is corrupt */
841 elog(ERROR, "bogus upper boundary types %d %d",
842 (int) a->u_ext, (int) b->u_ext);
843 }
844
846}
847
848Datum
850{
853 PG_GETARG_DATUM(1)));
854
855 PG_RETURN_BOOL(cmp < 0);
856}
857
858Datum
860{
863 PG_GETARG_DATUM(1)));
864
865 PG_RETURN_BOOL(cmp <= 0);
866}
867
868Datum
870{
873 PG_GETARG_DATUM(1)));
874
875 PG_RETURN_BOOL(cmp > 0);
876}
877
878Datum
880{
883 PG_GETARG_DATUM(1)));
884
885 PG_RETURN_BOOL(cmp >= 0);
886}
887
888
889Datum
891{
894 PG_GETARG_DATUM(1)));
895
896 PG_RETURN_BOOL(cmp != 0);
897}
898
899
900
901/*****************************************************************************
902 * Auxiliary functions
903 *****************************************************************************/
904
905/*
906 * The purpose of this routine is to print the given floating point
907 * value with exactly n significant digits. Its behaviour
908 * is similar to %.ng except it prints 8.00 where %.ng would
909 * print 8. Returns the length of the string written at "result".
910 *
911 * Caller must provide a sufficiently large result buffer; 16 bytes
912 * should be enough for all known float implementations.
913 */
914static int
915restore(char *result, float val, int n)
916{
917 char buf[25] = {
918 '0', '0', '0', '0', '0',
919 '0', '0', '0', '0', '0',
920 '0', '0', '0', '0', '0',
921 '0', '0', '0', '0', '0',
922 '0', '0', '0', '0', '\0'
923 };
924 char *p;
925 int exp;
926 int i,
927 dp,
928 sign;
929
930 /*
931 * Put a cap on the number of significant digits to avoid garbage in the
932 * output and ensure we don't overrun the result buffer. (n should not be
933 * negative, but check to protect ourselves against corrupted data.)
934 */
935 if (n <= 0)
936 n = FLT_DIG;
937 else
938 n = Min(n, FLT_DIG);
939
940 /* remember the sign */
941 sign = (val < 0 ? 1 : 0);
942
943 /* print, in %e style to start with */
944 sprintf(result, "%.*e", n - 1, val);
945
946 /* find the exponent */
947 p = strchr(result, 'e');
948
949 /* punt if we have 'inf' or similar */
950 if (p == NULL)
951 return strlen(result);
952
953 exp = atoi(p + 1);
954 if (exp == 0)
955 {
956 /* just truncate off the 'e+00' */
957 *p = '\0';
958 }
959 else
960 {
961 if (abs(exp) <= 4)
962 {
963 /*
964 * remove the decimal point from the mantissa and write the digits
965 * to the buf array
966 */
967 for (p = result + sign, i = 10, dp = 0; *p != 'e'; p++, i++)
968 {
969 buf[i] = *p;
970 if (*p == '.')
971 {
972 dp = i--; /* skip the decimal point */
973 }
974 }
975 if (dp == 0)
976 dp = i--; /* no decimal point was found in the above
977 * for() loop */
978
979 if (exp > 0)
980 {
981 if (dp - 10 + exp >= n)
982 {
983 /*
984 * the decimal point is behind the last significant digit;
985 * the digits in between must be converted to the exponent
986 * and the decimal point placed after the first digit
987 */
988 exp = dp - 10 + exp - n;
989 buf[10 + n] = '\0';
990
991 /* insert the decimal point */
992 if (n > 1)
993 {
994 dp = 11;
995 for (i = 23; i > dp; i--)
996 buf[i] = buf[i - 1];
997 buf[dp] = '.';
998 }
999
1000 /*
1001 * adjust the exponent by the number of digits after the
1002 * decimal point
1003 */
1004 if (n > 1)
1005 sprintf(&buf[11 + n], "e%d", exp + n - 1);
1006 else
1007 sprintf(&buf[11], "e%d", exp + n - 1);
1008
1009 if (sign)
1010 {
1011 buf[9] = '-';
1012 strcpy(result, &buf[9]);
1013 }
1014 else
1015 strcpy(result, &buf[10]);
1016 }
1017 else
1018 { /* insert the decimal point */
1019 dp += exp;
1020 for (i = 23; i > dp; i--)
1021 buf[i] = buf[i - 1];
1022 buf[11 + n] = '\0';
1023 buf[dp] = '.';
1024 if (sign)
1025 {
1026 buf[9] = '-';
1027 strcpy(result, &buf[9]);
1028 }
1029 else
1030 strcpy(result, &buf[10]);
1031 }
1032 }
1033 else
1034 { /* exp <= 0 */
1035 dp += exp - 1;
1036 buf[10 + n] = '\0';
1037 buf[dp] = '.';
1038 if (sign)
1039 {
1040 buf[dp - 2] = '-';
1041 strcpy(result, &buf[dp - 2]);
1042 }
1043 else
1044 strcpy(result, &buf[dp - 1]);
1045 }
1046 }
1047
1048 /* do nothing for abs(exp) > 4; %e must be OK */
1049 /* just get rid of zeroes after [eE]- and +zeroes after [Ee]. */
1050
1051 /* ... this is not done yet. */
1052 }
1053 return strlen(result);
1054}
1055
1056
1057/*
1058** Miscellany
1059*/
1060
1061/* find out the number of significant digits in a string representing
1062 * a floating point number
1063 */
1064int
1066{
1067 const char *p = s;
1068 int n,
1069 c,
1070 zeroes;
1071
1072 zeroes = 1;
1073 /* skip leading zeroes and sign */
1074 for (c = *p; (c == '0' || c == '+' || c == '-') && c != 0; c = *(++p));
1075
1076 /* skip decimal point and following zeroes */
1077 for (c = *p; (c == '0' || c == '.') && c != 0; c = *(++p))
1078 {
1079 if (c != '.')
1080 zeroes++;
1081 }
1082
1083 /* count significant digits (n) */
1084 for (c = *p, n = 0; c != 0; c = *(++p))
1085 {
1086 if (!((c >= '0' && c <= '9') || (c == '.')))
1087 break;
1088 if (c != '.')
1089 n++;
1090 }
1091
1092 if (!n)
1093 return zeroes;
1094
1095 return n;
1096}
#define Min(x, y)
Definition: c.h:961
void * yyscan_t
Definition: cubedata.h:67
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:643
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:272
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_RETURN_FLOAT4(x)
Definition: fmgr.h:366
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
#define GIST_LEAF(entry)
Definition: gist.h:171
const char * str
long val
Definition: informix.c:689
char sign
Definition: informix.c:693
int b
Definition: isn.c:69
int a
Definition: isn.c:68
int i
Definition: isn.c:72
void * palloc(Size size)
Definition: mcxt.c:1317
uint16 OffsetNumber
Definition: off.h:24
const void * data
static char * buf
Definition: pg_test_fsync.c:72
#define sprintf
Definition: port.h:241
#define qsort(a, b, c, d)
Definition: port.h:475
static bool DatumGetBool(Datum X)
Definition: postgres.h:95
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
uintptr_t Datum
Definition: postgres.h:69
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:207
char * c
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:743
Datum seg_le(PG_FUNCTION_ARGS)
Definition: seg.c:859
Datum gseg_decompress(PG_FUNCTION_ARGS)
Definition: seg.c:261
Datum seg_gt(PG_FUNCTION_ARGS)
Definition: seg.c:869
static Datum gseg_leaf_consistent(Datum key, Datum query, StrategyNumber strategy)
Definition: seg.c:433
Datum gseg_penalty(PG_FUNCTION_ARGS)
Definition: seg.c:271
Datum gseg_union(PG_FUNCTION_ARGS)
Definition: seg.c:224
Datum gseg_consistent(PG_FUNCTION_ARGS)
Definition: seg.c:197
Datum seg_center(PG_FUNCTION_ARGS)
Definition: seg.c:162
Datum seg_over_right(PG_FUNCTION_ARGS)
Definition: seg.c:617
Datum seg_contained(PG_FUNCTION_ARGS)
Definition: seg.c:547
Datum seg_overlap(PG_FUNCTION_ARGS)
Definition: seg.c:572
Datum seg_right(PG_FUNCTION_ARGS)
Definition: seg.c:606
#define PG_GETARG_SEG_P(n)
Definition: seg.c:23
Datum gseg_same(PG_FUNCTION_ARGS)
Definition: seg.c:413
static int gseg_picksplit_item_cmp(const void *a, const void *b)
Definition: seg.c:299
PG_MODULE_MAGIC
Definition: seg.c:31
Datum seg_lt(PG_FUNCTION_ARGS)
Definition: seg.c:849
#define DatumGetSegP(X)
Definition: seg.c:22
Datum seg_size(PG_FUNCTION_ARGS)
Definition: seg.c:715
Datum seg_union(PG_FUNCTION_ARGS)
Definition: seg.c:626
int significant_digits(const char *s)
Definition: seg.c:1065
Datum seg_upper(PG_FUNCTION_ARGS)
Definition: seg.c:178
static Datum gseg_internal_consistent(Datum key, Datum query, StrategyNumber strategy)
Definition: seg.c:477
Datum seg_ge(PG_FUNCTION_ARGS)
Definition: seg.c:879
Datum seg_lower(PG_FUNCTION_ARGS)
Definition: seg.c:170
Datum gseg_picksplit(PG_FUNCTION_ARGS)
Definition: seg.c:320
Datum seg_in(PG_FUNCTION_ARGS)
Definition: seg.c:104
Datum seg_cmp(PG_FUNCTION_ARGS)
Definition: seg.c:727
static int restore(char *result, float val, int n)
Definition: seg.c:915
Datum seg_inter(PG_FUNCTION_ARGS)
Definition: seg.c:666
Datum seg_left(PG_FUNCTION_ARGS)
Definition: seg.c:595
static void rt_seg_size(SEG *a, float *size)
Definition: seg.c:706
Datum seg_out(PG_FUNCTION_ARGS)
Definition: seg.c:121
PG_FUNCTION_INFO_V1(seg_in)
static Datum gseg_binary_union(Datum r1, Datum r2, int *sizep)
Definition: seg.c:526
Datum seg_over_left(PG_FUNCTION_ARGS)
Definition: seg.c:584
Datum gseg_compress(PG_FUNCTION_ARGS)
Definition: seg.c:255
Datum seg_contains(PG_FUNCTION_ARGS)
Definition: seg.c:538
Datum seg_same(PG_FUNCTION_ARGS)
Definition: seg.c:560
Datum seg_different(PG_FUNCTION_ARGS)
Definition: seg.c:890
void seg_yyerror(SEG *result, struct Node *escontext, yyscan_t yyscanner, const char *message)
Definition: segscan.l:67
void seg_scanner_init(const char *str, yyscan_t *yyscannerp)
Definition: segscan.l:99
struct SEG SEG
int seg_yyparse(SEG *result, struct Node *escontext, yyscan_t yyscanner)
void seg_scanner_finish(yyscan_t yyscanner)
Definition: segscan.l:116
static pg_noinline void Size size
Definition: slab.c:607
#define RTOldContainsStrategyNumber
Definition: stratnum.h:63
uint16 StrategyNumber
Definition: stratnum.h:22
#define RTOverlapStrategyNumber
Definition: stratnum.h:53
#define RTLeftStrategyNumber
Definition: stratnum.h:51
#define RTOverRightStrategyNumber
Definition: stratnum.h:54
#define RTRightStrategyNumber
Definition: stratnum.h:55
#define RTSameStrategyNumber
Definition: stratnum.h:56
#define RTContainsStrategyNumber
Definition: stratnum.h:57
#define RTOverLeftStrategyNumber
Definition: stratnum.h:52
#define RTOldContainedByStrategyNumber
Definition: stratnum.h:64
#define RTContainedByStrategyNumber
Definition: stratnum.h:58
Datum key
Definition: gist.h:161
int spl_nleft
Definition: gist.h:144
OffsetNumber * spl_right
Definition: gist.h:148
Datum spl_ldatum
Definition: gist.h:145
Datum spl_rdatum
Definition: gist.h:150
int spl_nright
Definition: gist.h:149
OffsetNumber * spl_left
Definition: gist.h:143
GISTENTRY vector[FLEXIBLE_ARRAY_MEMBER]
Definition: gist.h:237
int32 n
Definition: gist.h:236
Definition: segdata.h:5
char l_ext
Definition: segdata.h:10
char l_sigd
Definition: segdata.h:8
char u_sigd
Definition: segdata.h:9
float4 upper
Definition: segdata.h:7
char u_ext
Definition: segdata.h:11
float4 lower
Definition: segdata.h:6
OffsetNumber index
Definition: seg.c:39
float center
Definition: seg.c:38
SEG * data
Definition: seg.c:40