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