diff options
Diffstat (limited to 'contrib/seg')
-rw-r--r-- | contrib/seg/.gitignore | 6 | ||||
-rw-r--r-- | contrib/seg/Makefile | 38 | ||||
-rw-r--r-- | contrib/seg/data/test_seg.data | 2578 | ||||
-rw-r--r-- | contrib/seg/expected/security.out | 32 | ||||
-rw-r--r-- | contrib/seg/expected/seg.out | 1275 | ||||
-rw-r--r-- | contrib/seg/seg--1.0--1.1.sql | 63 | ||||
-rw-r--r-- | contrib/seg/seg--1.1--1.2.sql | 14 | ||||
-rw-r--r-- | contrib/seg/seg--1.1.sql | 395 | ||||
-rw-r--r-- | contrib/seg/seg--1.2--1.3.sql | 58 | ||||
-rw-r--r-- | contrib/seg/seg--1.3--1.4.sql | 8 | ||||
-rwxr-xr-x | contrib/seg/seg-validate.pl | 56 | ||||
-rw-r--r-- | contrib/seg/seg.c | 1094 | ||||
-rw-r--r-- | contrib/seg/seg.control | 6 | ||||
-rw-r--r-- | contrib/seg/segdata.h | 24 | ||||
-rw-r--r-- | contrib/seg/segparse.c | 1492 | ||||
-rw-r--r-- | contrib/seg/segparse.y | 177 | ||||
-rw-r--r-- | contrib/seg/segscan.c | 2095 | ||||
-rw-r--r-- | contrib/seg/segscan.l | 115 | ||||
-rwxr-xr-x | contrib/seg/sort-segments.pl | 30 | ||||
-rw-r--r-- | contrib/seg/sql/security.sql | 32 | ||||
-rw-r--r-- | contrib/seg/sql/seg.sql | 240 |
21 files changed, 9828 insertions, 0 deletions
diff --git a/contrib/seg/.gitignore b/contrib/seg/.gitignore new file mode 100644 index 0000000..69e73d2 --- /dev/null +++ b/contrib/seg/.gitignore @@ -0,0 +1,6 @@ +/segparse.c +/segscan.c +# Generated subdirectories +/log/ +/results/ +/tmp_check/ diff --git a/contrib/seg/Makefile b/contrib/seg/Makefile new file mode 100644 index 0000000..aee8826 --- /dev/null +++ b/contrib/seg/Makefile @@ -0,0 +1,38 @@ +# contrib/seg/Makefile + +MODULE_big = seg +OBJS = \ + $(WIN32RES) \ + seg.o \ + segparse.o + +EXTENSION = seg +DATA = seg--1.1.sql seg--1.1--1.2.sql seg--1.2--1.3.sql seg--1.3--1.4.sql \ + seg--1.0--1.1.sql +PGFILEDESC = "seg - line segment data type" + +HEADERS = segdata.h + +REGRESS = security seg + +EXTRA_CLEAN = y.tab.c y.tab.h + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/seg +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif + + +# segscan is compiled as part of segparse +segparse.o: segscan.c + +distprep: segparse.c segscan.c + +maintainer-clean: + rm -f segparse.c segscan.c diff --git a/contrib/seg/data/test_seg.data b/contrib/seg/data/test_seg.data new file mode 100644 index 0000000..6965806 --- /dev/null +++ b/contrib/seg/data/test_seg.data @@ -0,0 +1,2578 @@ +...10.3 +...10.5 +...3.5 +...3.9 +...4.9 +...40 +...5.6 +...5.8 +...6.0 +...6.6 +...6.7 +...6.75 +...7.0 +...7.2 +...7.3 +...7.5 +...7.6 +...7.8 +...8.0 +...8.5 +...8.6 +...8.8 +...8.9 +...9.0 +...9.2 +...9.3 +...9.5 +...9.6 +...90 +...<3.0 +...<5.8 +...<7 +...<7.0 +...<8.0 +...<8.2 +...<8.9 +...>10 +...>7.2 +...>7.7 +...>8.0 +...>82 +...>9.0 +< 1.0...3.8 +< 1.5...4.1 +< 1.5...4.15 +< 10...>11.6 +< 2...>4 +< 2.0...3.4 +< 2.0...4.2 +< 2.0...>8.0 +< 2.5...4.7 +< 2.5...5.5 +< 2.5...>8.5 +< 3...>5 +< 3.0... +< 3.0...4.5 +< 3.0...6.0 +< 3.0...6.5 +< 3.0...9.0 +< 3.0...>10 +< 3.0...>11.0 +< 3.0...>8.0 +< 3.0...>9.0 +< 3.0...>9.5 +< 3.5 +< 3.5...4.3 +< 3.5...5.3 +< 3.5...5.6 +< 3.5...6.0 +< 3.5...8.4 +< 3.6...>6.5 +< 3.7...5.4 +< 4...9.5 +< 4...>5 +< 4...>6.0 +< 4.0... +< 4.0...10.5 +< 4.0...5.3 +< 4.0...5.75 +< 4.0...6.0 +< 4.0...7.3 +< 4.0...7.5 +< 4.0...7.7 +< 4.0...8.5 +< 4.0...>12 +< 4.0...>5.0 +< 4.0...>6.0 +< 4.0...>7.5 +< 4.0...>8.0 +< 4.0...>8.1 +< 4.0...>9.0 +< 4.2...5.2 +< 4.2...5.3 +< 4.2...5.4 +< 4.2...6.2 +< 4.3...>9.0 +< 4.4 +< 4.4...6.0 +< 4.4...<6.0 +< 4.5...6.3 +< 4.5...7.2 +< 4.5...>12 +< 4.5...>5.0 +< 4.5...>5.5 +< 4.5...>6 +< 4.5...>7.5 +< 4.5...>8 +< 4.5...>9.5 +< 4.7...>9.3 +< 4.8...>6.4 +< 5...7.5 +< 5...7.7 +< 5...>7 +< 5...>8 +< 5...>8.0 +< 5.0 +< 5.0...10 +< 5.0...6.3 +< 5.0...7.4 +< 5.0...7.7 +< 5.0...8.1 +< 5.0...8.3 +< 5.0...8.5 +< 5.0...8.8 +< 5.0...9.5 +< 5.0...<9.0 +< 5.0...>10 +< 5.0...>10.0 +< 5.0...>10.5 +< 5.0...>11 +< 5.0...>6.0 +< 5.0...>6.6 +< 5.0...>7.5 +< 5.0...>8.0 +< 5.0...>8.5 +< 5.0...>8.6 +< 5.0...>9.0 +< 5.2...7.3 +< 5.2...8.2 +< 5.2...8.5 +< 5.2...>5.8 +< 5.2...>7.6 +< 5.3 +< 5.3...6.5 +< 5.3...7.5 +< 5.3...7.8 +< 5.4...6.35 +< 5.5...10 +< 5.5...6.3 +< 5.5...7.0 +< 5.5...7.5 +< 5.5...8.4 +< 5.5...8.5 +< 5.5...>10 +< 5.5...>10.0 +< 5.5...>10.5 +< 5.5...>6.5 +< 5.5...>7 +< 5.5...>7.5 +< 5.5...>8 +< 5.5...>8.0 +< 5.5...>8.5 +< 5.5...>8.7 +< 5.5...>8.9 +< 5.5...>9.0 +< 5.6...6.75 +< 5.75...>9.0 +< 5.8...7.8 +< 5.8...>11 +< 5.8...>8.2 +< 5.9...>8.0 +< 6...>10.5 +< 6...>8 +< 6...>9.5 +< 6.0 +< 6.0...6.8 +< 6.0...7.15 +< 6.0...7.6 +< 6.0...7.7 +< 6.0...8.0 +< 6.0...8.2 +< 6.0...8.5 +< 6.0...9.0 +< 6.0...9.5 +< 6.0...>10 +< 6.0...>10.0 +< 6.0...>11 +< 6.0...>7.0 +< 6.0...>8.0 +< 6.0...>8.2 +< 6.0...>8.5 +< 6.0...>8.6 +< 6.0...>9.0 +< 6.0...>9.6 +< 6.3...9.5 +< 6.3...>6.7 +< 6.3...>7.8 +< 6.35...>7.7 +< 6.4...>8.0 +< 6.4...>8.7 +< 6.5...11 +< 6.5...7.25 +< 6.5...8.0 +< 6.5...8.2 +< 6.5...8.4 +< 6.5...8.5 +< 6.5...9.7 +< 6.5...>10.0 +< 6.5...>10.5 +< 6.5...>7.5 +< 6.5...>8.0 +< 6.5...>8.5 +< 6.5...>8.6 +< 6.5...>8.7 +< 6.5...>9.0 +< 6.5...>9.5 +< 6.6...>7.5 +< 6.6...>8.5 +< 6.8...7.8 +< 6.8...9.5 +< 6.8...>7.5 +< 6.8...>8.6 +< 6.8...>9.0 +< 6.9...9.0 +< 7...9.2 +< 7...>11 +< 7...>7.5 +< 7...>9.5 +< 7.0 +< 7.0...10 +< 7.0...10.5 +< 7.0...11.0 +< 7.0...8.2 +< 7.0...8.3 +< 7.0...8.4 +< 7.0...8.55 +< 7.0...8.7 +< 7.0...8.8 +< 7.0...9.0 +< 7.0...<8.0 +< 7.0...>10.5 +< 7.0...>11 +< 7.0...>11.0 +< 7.0...>7.0 +< 7.0...>7.3 +< 7.0...>7.4 +< 7.0...>7.5 +< 7.0...>7.75 +< 7.0...>7.8 +< 7.0...>8.0 +< 7.0...>8.2 +< 7.0...>8.5 +< 7.0...>8.6 +< 7.0...>8.9 +< 7.0...>9.0 +< 7.0...>9.5 +< 7.2...8.3 +< 7.2...>7.5 +< 7.2...>7.8 +< 7.2...>8.0 +< 7.2...>8.2 +< 7.2...>8.6 +< 7.2...>8.8 +< 7.4...>7.8 +< 7.4...>8.0 +< 7.4...>8.1 +< 7.4...>8.6 +< 7.4...>8.8 +< 7.5...9.0 +< 7.5...>10 +< 7.5...>8.0 +< 7.5...>8.5 +< 7.5...>8.7 +< 7.5...>9 +< 7.5...>9.0 +< 7.5...>9.5 +< 7.6...>7.8 +< 7.6...>8.0 +< 7.6...>8.5 +< 7.6...>8.6 +< 7.6...>8.9 +< 7.8...>9.0 +< 7.9...>8.3 +< 8.0 +< 8.0...>10.0 +< 8.0...>8.5 +< 8.0...>9.0 +< 8.0...>9.4 +< 8.0...>9.5 +< 8.2...9.8 +< 8.2...>8.6 +< 8.5...>10.5 +< 8.5...>11 +< 8.5...>9.5 +< 9...10.5 +<1.0...3.5 +<1.0...3.7 +<1.0...4.0 +<1.0...>13.0 +<1.0...>5.5 +<10.5...11.5 +<12.0...12.5 +<2...10 +<2...>4 +<2.0 +<2.0...11 +<2.0...3.5 +<2.0...5.7 +<2.0...6.0 +<2.0...6.8 +<2.0...9.7 +<2.0...>6.5 +<2.0...>9.0 +<2.3... +<2.3...>11.0 +<2.4...6.8 +<2.5...7.7 +<2.5...>8.0 +<2.8...>8.0 +<3.0...4.6 +<3.0...5.5 +<3.0...6.0 +<3.0...6.3 +<3.0...6.4 +<3.0...6.8 +<3.0...7.0 +<3.0...7.5 +<3.0...8.3 +<3.0...>10.5 +<3.0...>5.0 +<3.0...>7.0 +<3.0...>7.2 +<3.0...>8.5 +<3.0...>8.7 +<3.0...>9.0 +<3.5...6.0 +<3.5...8.0 +<3.5...<7.0 +<3.5...>10.0 +<3.55...5.3 +<3.7...4.9 +<3.7...5.0 +<4...6.5 +<4.0...10.0 +<4.0...10.5 +<4.0...6.1 +<4.0...6.3 +<4.0...6.5 +<4.0...7.7 +<4.0...8.2 +<4.0...<9.0 +<4.0...>10 +<4.0...>10.0 +<4.0...>10.5 +<4.0...>6.0 +<4.0...>8.0 +<4.0...>9.0 +<4.1...>8.0 +<4.3...7.6 +<4.5...6.3 +<4.5...6.5 +<4.5...>6.5 +<4.5...>9.5 +<4.8...>7.4 +<4.9...>9.5 +<5...>6 +<5...>6.0 +<5...>8 +<5.0...10.0 +<5.0...6.0 +<5.0...6.6 +<5.0...6.8 +<5.0...7.0 +<5.0...7.5 +<5.0...8.2 +<5.0...9.5 +<5.0...>11.0 +<5.0...>5.5 +<5.0...>7.0 +<5.0...>8.0 +<5.0...>9.0 +<5.2...7.5 +<5.2...>6.8 +<5.2...>8.0 +<5.3...10.2 +<5.3...>10.5 +<5.4...8.0 +<5.4...8.5 +<5.4...>8.2 +<5.4...>9.1 +<5.5...6.5 +<5.5...7.0 +<5.5...7.5 +<5.5...8.2 +<5.5...8.3 +<5.5...8.5 +<5.5...8.6 +<5.5...>10.0 +<5.5...>7.0 +<5.5...>7.5 +<5.5...>8.0 +<5.5...>8.5 +<5.5...>9.0 +<5.6...7.5 +<5.6...>6.4 +<5.6...>7.4 +<5.6...>8.0 +<5.6...>8.5 +<5.7...>7.1 +<5.8...7.4 +<5.8...>6.7 +<5.8...>6.8 +<5.8...>7.0 +<5.8...>7.8 +<5.8...>8.8 +<5.85...>9.5 +<6...>9 +<6.0...10.0 +<6.0...6.8 +<6.0...7.1 +<6.0...7.2 +<6.0...7.7 +<6.0...8.0 +<6.0...8.2 +<6.0...8.4 +<6.0...8.5 +<6.0...8.6 +<6.0...9.1 +<6.0...9.2 +<6.0...9.3 +<6.0...9.5 +<6.0...>10 +<6.0...>11.0 +<6.0...>7.0 +<6.0...>7.5 +<6.0...>7.6 +<6.0...>7.9 +<6.0...>8.0 +<6.0...>8.3 +<6.0...>8.5 +<6.0...>8.6 +<6.0...>9.0 +<6.0...>9.2 +<6.0...>9.5 +<6.1...8.4 +<6.1...>6.6 +<6.1...>8.1 +<6.2 +<6.2...6.9 +<6.2...8.3 +<6.2...>7.5 +<6.2...>8.5 +<6.2...>8.7 +<6.3...10.0 +<6.3...7.4 +<6.3...9.6 +<6.3...>7.0 +<6.3...>8.0 +<6.4...7.6 +<6.4...8.5 +<6.4...>8.5 +<6.4...>9.0 +<6.5...7.8 +<6.5...8.2 +<6.5...9.2 +<6.5...>7.0 +<6.5...>7.5 +<6.5...>8.0 +<6.5...>8.5 +<6.5...>8.7 +<6.5...>9.0 +<6.5...>9.5 +<6.6 +<6.6...8.0 +<6.8...8.0 +<6.8...8.2 +<6.8...>7.5 +<6.8...>8.5 +<6.8...>9.5 +<7...9 +<7...>10 +<7.0...7.5 +<7.0...9.0 +<7.0...9.0 +<7.0...9.4 +<7.0...9.5 +<7.0...9.5 +<7.0...>10 +<7.0...>10.0 +<7.0...>11.5 +<7.0...>7.5 +<7.0...>8.0 +<7.0...>8.3 +<7.0...>8.4 +<7.0...>8.5 +<7.0...>9.0 +<7.2...8.8 +<7.2...9.0 +<7.2...>8.2 +<7.2...>8.8 +<7.2...>9.5 +<7.3...>8.0 +<7.4...8.8 +<7.4...9.6 +<7.4...>8.5 +<7.4...>8.7 +<7.5...8.5 +<7.5...<9.0 +<7.5...>8.0 +<7.5...>8.5 +<7.5...>9.5 +<7.6...>8.4 +<7.6...>9.4 +<7.8...>10.2 +<7.8...>8.2 +<8.0 +<8.0...10.0 +<8.0...>8.5 +<8.0...>8.8 +<8.0...>9.0 +<8.2...>10.2 +<8.5...9.6 +<8.5...>9.0 +<8.5...>9.5 +<8.6...>10.6 +<9.1...10.3 +<9.2...>11.0 +<9.5...12 +<9.5...>12.2 +> 11.0 +> 3.0...<7.0 +> 4.0...<10.0 +> 4.0...<9.0 +> 4.5...<9.0 +> 5.0 +> 5.0...<10.0 +> 5.0...<11 +> 5.5... +> 5.6 +> 5.9...<9.5 +> 6.0...8.0 +> 6.0...<11.5 +> 6.0...<8.0 +> 6.0...>10.0 +> 6.2...<7.4 +> 7.0...<10 +> 7.0...>8.5 +> 7.0...>8.6 +> 7.0...>8.7 +> 7.15... +> 8.0 +> 8.7 +> 9.3 +> 9.5 +>10.5 +>120 +>2.3... +>3.0...<7.0 +>3.8...<8.0 +>4.0...<10 +>5.0...<7.0 +>5.0...>8.0 +>5.0...>9.2 +>5.25...6.5 +>5.5...>9.3 +>5.6...<8.2 +>6.0...>11.0 +>6.5...>8.0 +>6.6...<7.3 +>6.8...>8.5 +>6.9...>8.0 +>7.0 +>7.0...<9.0 +>7.0...<9.5 +>7.3... +>7.5...<10.5 +>8.0 +>8.4 +>8.5 +>9.0 +>9.4 +>9.5 +>95 +~10 +~23 +~5.0...>9.0 +~6.0 +~6.4...~8.5 +~6.8 +~7.0 +~7.5 +~8.0 +~8.0...~10.0 +1.0 +1.0...4.0 +1.0...5.0 +1.1 +1.1...3.6 +1.2...3.2 +1.2...3.5 +1.3...12.0 +1.4...2.0 +1.4...8.2 +1.5 +1.5...10.5 +1.5...4.2 +1.5...4.5 +1.6...3.8 +1.6...7.2 +1.7 +1.7...2.4 +1.7...3.2 +1.7...5.0 +1.7...5.7 +1.8 +1.8...3.8 +1.8...>9.0 +1.9...3.6 +2 +2.0 +2.0...10.0 +2.0...11.0 +2.0...11.5 +2.0...2.5 +2.0...3.2 +2.0...3.5 +2.0...4.0 +2.0...4.3 +2.0...4.4 +2.0...4.6 +2.0...4.75 +2.0...4.8 +2.0...5.0 +2.0...5.5 +2.0...6.5 +2.0...7.0 +2.0...7.5 +2.0...8.0 +2.0...9.0 +2.0...>10 +2.0...>4.0 +2.0...>5.5 +2.1 +2.1...11.8 +2.1...4.2 +2.2 +2.2...11.2 +2.2...4.1 +2.2...4.2 +2.2...5.9 +2.2...6.4 +2.2...6.8 +2.3...10.6 +2.3...4.1 +2.3...4.3 +2.3...4.5 +2.3...4.7 +2.3...6.0 +2.4 +2.4...11.3 +2.4...4.5 +2.4...5.6 +2.4...5.7 +2.4...6.3 +2.5 +2.5...11 +2.5...11.2 +2.5...11.5 +2.5...11.8 +2.5...3.0 +2.5...3.7 +2.5...4.1 +2.5...4.5 +2.5...4.6 +2.5...5.0 +2.5...5.1 +2.5...5.5 +2.5...6.0 +2.5...6.3 +2.5...7.0 +2.5...9.0 +2.5...>3.5 +2.5...>4.0 +2.52 +2.56 +2.6... +2.6...10.0 +2.6...9.3 +2.6...>4.0 +2.6...>9.4 +2.62 +2.7 +2.7...12.0 +2.7...3.7 +2.7...3.8 +2.7...4.5 +2.7...4.7 +2.7...6.0 +2.7...6.4 +2.7...7.0 +2.7...8.0 +2.75...5.25 +2.79 +2.8 +2.8...11.0 +2.8...3.4 +2.8...4.0 +2.8...7.0 +2.8...8.0 +2.8...9.0 +2.8...9.7 +2.9...3.7 +2.9...4.5 +2.9...5.0 +2.9...5.6 +2.9...6.1 +2.9...7.6 +2.9...9.0 +2.97 +3 +3...10.0 +3...10.5 +3...5.5 +3...58 +3...6 +3...8 +3.0 +3.0...10 +3.0...10.0 +3.0...10.5 +3.0...11.0 +3.0...3.5 +3.0...4.0 +3.0...4.5 +3.0...4.9 +3.0...5.0 +3.0...5.4 +3.0...5.6 +3.0...5.65 +3.0...6.0 +3.0...6.3 +3.0...6.5 +3.0...6.7 +3.0...6.9 +3.0...7.0 +3.0...7.2 +3.0...7.5 +3.0...8.0 +3.0...8.5 +3.0...8.7 +3.0...9.0 +3.0...9.7 +3.0...>10 +3.0...>10.0 +3.0...>8.0 +3.00...5.0 +3.1 +3.1...11.5 +3.1...5.2 +3.1...5.8 +3.1...6.8 +3.1...7.8 +3.15...7.25 +3.2 +3.2...10.0 +3.2...4.2 +3.2...4.6 +3.2...5.4 +3.2...5.8 +3.2...6.25 +3.2...6.8 +3.2...8.1 +3.2...>8.0 +3.2...>9.9 +3.22 +3.3 +3.3...4.7 +3.3...5.3 +3.3...5.5 +3.3...5.6 +3.3...6.0 +3.3...6.5 +3.3...6.7 +3.3...7.2 +3.3...7.4 +3.3...7.5 +3.3...7.8 +3.3...9.0 +3.4 +3.4...4.1 +3.4...4.7 +3.4...5.5 +3.4...6.2 +3.4...6.4 +3.4...8.2 +3.4...>8.0 +3.5 +3.5...10 +3.5...10.0 +3.5...10.5 +3.5...10.8 +3.5...11.0 +3.5...11.5 +3.5...12.2 +3.5...4.0 +3.5...4.4 +3.5...4.5 +3.5...5.0 +3.5...5.3 +3.5...5.5 +3.5...5.6 +3.5...6 +3.5...6.0 +3.5...6.3 +3.5...6.4 +3.5...6.5 +3.5...6.6 +3.5...6.7 +3.5...7.0 +3.5...7.2 +3.5...7.3 +3.5...7.5 +3.5...8.5 +3.5...8.6 +3.5...8.7 +3.5...9.0 +3.5...9.5 +3.5...>11.0 +3.5...>5.0 +3.5...>8.5 +3.5...>9.0 +3.6 +3.6...3.8 +3.6...4.55 +3.6...4.6 +3.6...4.8 +3.6...5.4 +3.6...5.5 +3.6...6 +3.6...6.0 +3.6...6.6 +3.6...6.8 +3.6...7.0 +3.6...7.7 +3.6...8.6 +3.6...8.7 +3.6...8.8 +3.7 +3.7...10.0 +3.7...10.6 +3.7...4.6 +3.7...5.3 +3.7...6.2 +3.7...6.3 +3.7...6.5 +3.7...6.7 +3.7...8.2 +3.7...8.3 +3.7...9.1 +3.7...>10 +3.7...>11 +3.75...5.7 +3.8 +3.8...10 +3.8...4.0 +3.8...4.5 +3.8...4.8 +3.8...5.5 +3.8...5.8 +3.8...5.9 +3.8...6.2 +3.8...7.7 +3.8...8.3 +3.8...8.7 +3.9 +3.9...5.5 +3.9...6.8 +3.9...7.8 +3.9...>7.5 +3.9...>8.5 +3.9...>9.0 +3.95 +4 +4...10 +4...11.0 +4...12 +4...5 +4...6.9 +4...7 +4...7.5 +4...8 +4...9 +4...>11 +4...>8 +4.0 +4.0... +4.0...10 +4.0...10.0 +4.0...10.4 +4.0...10.5 +4.0...11.0 +4.0...11.7 +4.0...12.5 +4.0...13.0 +4.0...4.4 +4.0...4.5 +4.0...4.8 +4.0...5.0 +4.0...5.1 +4.0...5.2 +4.0...5.5 +4.0...5.7 +4.0...5.75 +4.0...5.8 +4.0...6.0 +4.0...6.1 +4.0...6.2 +4.0...6.3 +4.0...6.5 +4.0...60 +4.0...7.0 +4.0...7.2 +4.0...7.3 +4.0...7.5 +4.0...7.7 +4.0...7.9 +4.0...8.0 +4.0...8.1 +4.0...8.2 +4.0...8.3 +4.0...8.5 +4.0...8.8 +4.0...9.0 +4.0...9.4 +4.0...>10 +4.0...>11 +4.0...>9.0 +4.1 +4.1...10.5 +4.1...5.6 +4.1...5.8 +4.1...6.0 +4.1...7.2 +4.1...8.0 +4.1...9.1 +4.15...5.25 +4.15...6.25 +4.15...6.5 +4.2 +4.2...11.0 +4.2...11.5 +4.2...11.7 +4.2...5.0 +4.2...5.3 +4.2...5.35 +4.2...5.4 +4.2...5.6 +4.2...5.7 +4.2...6.0 +4.2...6.3 +4.2...6.4 +4.2...6.7 +4.2...7.1 +4.2...7.2 +4.2...7.3 +4.2...8.0 +4.2...8.4 +4.2...9.5 +4.2...>7.0 +4.2...>7.3 +4.2...>9.0 +4.2...>9.5 +4.25 +4.25...5.00 +4.25...9.75 +4.3 +4.3...10.3 +4.3...5.3 +4.3...5.7 +4.3...5.8 +4.3...6.0 +4.3...6.3 +4.3...6.5 +4.3...6.8 +4.3...7.0 +4.3...7.2 +4.3...7.3 +4.3...7.5 +4.3...7.6 +4.3...8 +4.3...8.2 +4.3...8.5 +4.3...8.6 +4.3...>5.0 +4.3...>6.0 +4.3...>7.0 +4.3...>8.0 +4.35 +4.4 +4.4...10.7 +4.4...4.6 +4.4...4.8 +4.4...6.0 +4.4...6.2 +4.4...6.4 +4.4...6.6 +4.4...6.7 +4.4...7.0 +4.4...7.2 +4.4...7.5 +4.4...7.6 +4.4...8.5 +4.4...9.3 +4.5 +4.5...10 +4.5...10.0 +4.5...10.5 +4.5...11.0 +4.5...11.5 +4.5...115 +4.5...12.5 +4.5...4.8 +4.5...5.0 +4.5...5.2 +4.5...5.5 +4.5...5.7 +4.5...5.8 +4.5...6.0 +4.5...6.2 +4.5...6.4 +4.5...6.5 +4.5...6.8 +4.5...7 +4.5...7.0 +4.5...7.1 +4.5...7.3 +4.5...7.5 +4.5...7.6 +4.5...7.7 +4.5...7.8 +4.5...7.9 +4.5...8.0 +4.5...8.3 +4.5...8.5 +4.5...8.6 +4.5...8.7 +4.5...8.8 +4.5...8.9 +4.5...9.0 +4.5...9.3 +4.5...9.4 +4.5...9.5 +4.5...<12 +4.5...>10 +4.5...>12 +4.5...>6.0 +4.5...>7.0 +4.5...>7.5 +4.5...>8.0 +4.5...>8.5 +4.5...>9.0 +4.6 +4.6 +4.6...4.8 +4.6...5.0 +4.6...5.2 +4.6...6.3 +4.6...6.4 +4.6...6.5 +4.6...6.6 +4.6...7.0 +4.6...7.2 +4.6...7.4 +4.6...7.5 +4.6...8.2 +4.6...8.5 +4.6...8.6 +4.6...8.7 +4.6...<6.5 +4.6...>10 +4.6...>11 +4.6...>7.4 +4.6...>8.0 +4.6...~7.0 +4.7 +4.7...10.8 +4.7...11 +4.7...11.8 +4.7...5.6 +4.7...6.0 +4.7...6.2 +4.7...6.3 +4.7...6.6 +4.7...6.7 +4.7...7.0 +4.7...7.4 +4.7...7.5 +4.7...7.7 +4.7...7.8 +4.7...8.0 +4.7...8.3 +4.7...8.4 +4.7...8.5 +4.7...9.3 +4.7...9.5 +4.7...9.6 +4.7...9.7 +4.7...>10 +4.7...>10.0 +4.7...>10.5 +4.7...>6.5 +4.7...>8.0 +4.75 +4.8 +4.8... +4.8...10.3 +4.8...11.5 +4.8...11.6 +4.8...12.5 +4.8...5.2 +4.8...5.9 +4.8...6.0 +4.8...6.2 +4.8...6.3 +4.8...7.0 +4.8...7.3 +4.8...7.4 +4.8...7.5 +4.8...7.6 +4.8...7.7 +4.8...7.75 +4.8...8.0 +4.8...8.2 +4.8...8.4 +4.8...8.6 +4.8...9.0 +4.8...9.3 +4.8...9.7 +4.8...>10.0 +4.8...>8.0 +4.8...>9.0 +4.85 +4.9 +4.9... +4.9...6.5 +4.9...7.2 +4.9...7.8 +4.9...8.2 +4.9...8.3 +4.9...9.0 +4.9...9.5 +4.9...<6.0 +4.9...>12 +4.9...>7.5 +4.9...>9.5 +5 +5...10.0 +5...10.5 +5...11 +5...11.5 +5...12 +5...30 +5...6 +5...6.6 +5...7 +5...8 +5...8.5 +5...9 +5...9.5 +5.0 +5.0...10 +5.0...10.0 +5.0...10.2 +5.0...10.3 +5.0...10.5 +5.0...11 +5.0...11.0 +5.0...11.2 +5.0...11.4 +5.0...11.5 +5.0...11.6 +5.0...11.7 +5.0...12.0 +5.0...5.5 +5.0...5.7 +5.0...6.0 +5.0...6.1 +5.0...6.2 +5.0...6.4 +5.0...6.5 +5.0...6.6 +5.0...6.8 +5.0...6.9 +5.0...7.0 +5.0...7.2 +5.0...7.3 +5.0...7.4 +5.0...7.5 +5.0...7.6 +5.0...7.7 +5.0...7.8 +5.0...8.0 +5.0...8.2 +5.0...8.3 +5.0...8.4 +5.0...8.5 +5.0...8.6 +5.0...8.7 +5.0...9.0 +5.0...9.0 +5.0...9.2 +5.0...9.5 +5.0...>10 +5.0...>10.0 +5.0...>11 +5.0...>12 +5.0...>12.0 +5.0...>7.0 +5.0...>8.0 +5.0...>8.4 +5.0...>8.5 +5.0...>9.0 +5.02...6.74 +5.1 +5.1...5.3 +5.1...5.4 +5.1...6.2 +5.1...6.3 +5.1...6.4 +5.1...6.6 +5.1...6.8 +5.1...7.0 +5.1...7.2 +5.1...7.3 +5.1...7.8 +5.1...8.0 +5.1...8.3 +5.1...8.7 +5.1...>7.0 +5.15 +5.2 +5.2...10.0 +5.2...10.8 +5.2...11.5 +5.2...5.3 +5.2...5.5 +5.2...5.7 +5.2...6.0 +5.2...6.2 +5.2...6.4 +5.2...6.7 +5.2...6.8 +5.2...6.9 +5.2...7.0 +5.2...7.3 +5.2...7.4 +5.2...7.5 +5.2...7.6 +5.2...7.7 +5.2...7.9 +5.2...8.0 +5.2...8.2 +5.2...8.4 +5.2...8.5 +5.2...8.7 +5.2...8.8 +5.2...9.0 +5.2...9.5 +5.2...9.6 +5.2...9.7 +5.2...9.9 +5.2...>10.0 +5.2...>11 +5.2...>12 +5.2...>6.5 +5.2...>7.0 +5.2...>7.5 +5.2...>8 +5.2...>8.0 +5.25...7.5 +5.25...8.5 +5.25...>12 +5.3 +5.3... +5.3...10.0 +5.3...10.1 +5.3...10.2 +5.3...10.5 +5.3...10.6 +5.3...11.5 +5.3...13 +5.3...5.5 +5.3...5.8 +5.3...7.0 +5.3...7.2 +5.3...7.4 +5.3...7.5 +5.3...7.6 +5.3...7.8 +5.3...8.0 +5.3...8.2 +5.3...8.3 +5.3...8.6 +5.3...8.7 +5.3...8.8 +5.3...8.9 +5.3...9.0 +5.3...9.3 +5.3...9.5 +5.3...9.7 +5.3...9.9 +5.3...>7.8 +5.3...>9.0 +5.3...>90 +5.35 +5.4 +5.4... +5.4...10 +5.4...10.5 +5.4...5.8 +5.4...6.8 +5.4...7.0 +5.4...7.1 +5.4...7.2 +5.4...7.3 +5.4...7.7 +5.4...7.8 +5.4...8.2 +5.4...8.5 +5.4...9.4 +5.4...>10.0 +5.4...>11.0 +5.4...>9.0 +5.45 +5.5 +5.5... +5.5...10.0 +5.5...10.2 +5.5...10.5 +5.5...11 +5.5...11.5 +5.5...11.7 +5.5...12 +5.5...12.5 +5.5...13.5 +5.5...5.6 +5.5...5.7 +5.5...5.8 +5.5...6 +5.5...6.0 +5.5...6.2 +5.5...6.3 +5.5...6.5 +5.5...6.7 +5.5...6.8 +5.5...7.0 +5.5...7.1 +5.5...7.2 +5.5...7.3 +5.5...7.4 +5.5...7.5 +5.5...7.6 +5.5...7.7 +5.5...7.9 +5.5...8.0 +5.5...8.1 +5.5...8.2 +5.5...8.5 +5.5...8.6 +5.5...8.7 +5.5...9.0 +5.5...9.1 +5.5...9.3 +5.5...9.5 +5.5...9.7 +5.5...<6.8 +5.5...>10 +5.5...>10.0 +5.5...>11 +5.5...>11.0 +5.5...>12 +5.5...>7.0 +5.5...>8.0 +5.5...>9.0 +5.5...>9.5 +5.55 +5.55...7.8 +5.56 +5.6 +5.6...10 +5.6...10.1 +5.6...6.0 +5.6...6.2 +5.6...6.4 +5.6...6.6 +5.6...7.0 +5.6...7.1 +5.6...7.2 +5.6...7.3 +5.6...7.4 +5.6...7.5 +5.6...7.6 +5.6...7.7 +5.6...8.0 +5.6...8.3 +5.6...8.4 +5.6...8.5 +5.6...8.75 +5.6...8.8 +5.6...9 +5.6...9.0 +5.6...9.4 +5.6...9.5 +5.6...9.6 +5.6...>11 +5.6...>7.0 +5.6...>7.5 +5.6...>8.0 +5.6...>9.0 +5.65 +5.7 +5.7... +5.7...10 +5.7...10.0 +5.7...11 +5.7...6.0 +5.7...6.2 +5.7...6.3 +5.7...6.5 +5.7...6.8 +5.7...7.0 +5.7...7.2 +5.7...7.3 +5.7...7.5 +5.7...7.6 +5.7...7.65 +5.7...7.7 +5.7...7.8 +5.7...7.9 +5.7...8.0 +5.7...8.4 +5.7...8.5 +5.7...8.7 +5.7...8.9 +5.7...9.0 +5.7...9.2 +5.7...9.4 +5.7...9.7 +5.7...>10.0 +5.7...>11 +5.7...>6.6 +5.7...>7.2 +5.7...>8.5 +5.7...>9.0 +5.73 +5.75 +5.75...7.3 +5.8 +5.8...10.0 +5.8...11 +5.8...6.0 +5.8...6.2 +5.8...6.5 +5.8...6.7 +5.8...6.8 +5.8...6.9 +5.8...7.0 +5.8...7.2 +5.8...7.3 +5.8...7.4 +5.8...7.5 +5.8...7.6 +5.8...7.7 +5.8...7.8 +5.8...8.0 +5.8...8.1 +5.8...8.2 +5.8...8.3 +5.8...8.4 +5.8...8.5 +5.8...8.6 +5.8...8.8 +5.8...9.0 +5.8...9.2 +5.8...9.3 +5.8...9.8 +5.8...>10.5 +5.8...>11 +5.8...>6.7 +5.8...>6.8 +5.8...>8.0 +5.8...>9.0 +5.85 +5.87 +5.9 +5.9... +5.9...10.2 +5.9...6.0 +5.9...6.5 +5.9...7.3 +5.9...7.5 +5.9...7.7 +5.9...8.0 +5.9...8.2 +5.9...8.3 +5.9...8.4 +5.9...8.5 +5.9...8.7 +5.9...9.0 +5.9...>7.0 +5.9...>8.5 +5.92 +5.95...8.0 +6 +6...10 +6...11 +6...11.5 +6...6.5 +6...8 +6...8.0 +6...8.5 +6...9 +6...9.2 +6...9.3 +6...>10 +6...>12 +6...>7.2 +6...>8 +6.0 +6.0 +6.0...10 +6.0...10.0 +6.0...10.2 +6.0...10.3 +6.0...10.4 +6.0...10.5 +6.0...11 +6.0...11.0 +6.0...11.5 +6.0...13 +6.0...6.2 +6.0...6.3 +6.0...6.4 +6.0...6.5 +6.0...6.6 +6.0...6.7 +6.0...6.8 +6.0...7.0 +6.0...7.2 +6.0...7.3 +6.0...7.4 +6.0...7.5 +6.0...7.6 +6.0...7.7 +6.0...7.8 +6.0...8.0 +6.0...8.1 +6.0...8.2 +6.0...8.3 +6.0...8.4 +6.0...8.5 +6.0...8.5 +6.0...8.6 +6.0...8.7 +6.0...8.9 +6.0...9.0 +6.0...9.1 +6.0...9.2 +6.0...9.3 +6.0...9.4 +6.0...9.5 +6.0...9.7 +6.0...9.8 +6.0...9.9 +6.0...>10.0 +6.0...>10.5 +6.0...>11 +6.0...>7.0 +6.0...>7.5 +6.0...>8.0 +6.0...>8.2 +6.0...>8.5 +6.0...>8.7 +6.0...>9.0 +6.0...>9.5 +6.01 +6.1 +6.1... +6.1...10 +6.1...10.8 +6.1...6.2 +6.1...6.6 +6.1...6.8 +6.1...6.9 +6.1...7.0 +6.1...7.2 +6.1...7.5 +6.1...7.6 +6.1...7.7 +6.1...7.8 +6.1...7.9 +6.1...8.0 +6.1...8.2 +6.1...8.5 +6.1...8.7 +6.1...8.9 +6.1...9.0 +6.1...9.3 +6.1...9.4 +6.1...>12 +6.1...>8.0 +6.1...>8.2 +6.1...>8.5 +6.1...>9.0 +6.1...>9.5 +6.15 +6.18 +6.2 +6.2...10 +6.2...10.0 +6.2...10.5 +6.2...11 +6.2...6.4 +6.2...6.5 +6.2...6.8 +6.2...6.9 +6.2...7.0 +6.2...7.2 +6.2...7.4 +6.2...7.5 +6.2...7.6 +6.2...7.7 +6.2...7.8 +6.2...8.0 +6.2...8.1 +6.2...8.2 +6.2...8.3 +6.2...8.4 +6.2...8.5 +6.2...8.6 +6.2...8.7 +6.2...8.8 +6.2...9.0 +6.2...9.1 +6.2...9.2 +6.2...9.5 +6.2...9.7 +6.2...9.8 +6.2...>10.5 +6.2...>11.5 +6.2...>7.1 +6.2...>7.8 +6.2...>8.0 +6.2...>9.0 +6.2...>9.5 +6.23...8.07 +6.24 +6.25 +6.25...7.5 +6.25...>9.0 +6.3 +6.3... +6.3...10.0 +6.3...10.2 +6.3...10.4 +6.3...10.5 +6.3...6.4 +6.3...6.5 +6.3...6.6 +6.3...6.7 +6.3...6.8 +6.3...7.3 +6.3...7.5 +6.3...7.7 +6.3...7.8 +6.3...7.9 +6.3...8.0 +6.3...8.2 +6.3...8.3 +6.3...8.5 +6.3...8.6 +6.3...8.7 +6.3...8.9 +6.3...9.0 +6.3...9.1 +6.3...9.2 +6.3...9.3 +6.3...9.4 +6.3...9.5 +6.3...9.7 +6.3...9.8 +6.3...>10.0 +6.3...>11 +6.3...>7.5 +6.3...>7.8 +6.3...>8.0 +6.3...>8.1 +6.3...>8.3 +6.3...>8.5 +6.3...>9.0 +6.3...>9.2 +6.35 +6.4 +6.4...7.7 +6.4...10 +6.4...10.8 +6.4...6.7 +6.4...6.8 +6.4...7.0 +6.4...7.2 +6.4...7.4 +6.4...7.5 +6.4...7.6 +6.4...7.7 +6.4...7.8 +6.4...8.0 +6.4...8.1 +6.4...8.2 +6.4...8.3 +6.4...8.4 +6.4...8.6 +6.4...8.7 +6.4...8.8 +6.4...9.0 +6.4...9.3 +6.4...>10 +6.4...>11.0 +6.4...>7.8 +6.4...>8.0 +6.4...>8.5 +6.4...>8.6 +6.4...>9.0 +6.4...>9.1 +6.4...>9.2 +6.4...>9.5 +6.42 +6.5 +6.5 +6.5... +6.5...10 +6.5...10.0 +6.5...10.2 +6.5...10.3 +6.5...10.5 +6.5...11 +6.5...11.0 +6.5...11.5 +6.5...12.0 +6.5...6.7 +6.5...6.75 +6.5...6.8 +6.5...6.9 +6.5...7.0 +6.5...7.1 +6.5...7.3 +6.5...7.4 +6.5...7.5 +6.5...7.6 +6.5...7.7 +6.5...7.8 +6.5...7.9 +6.5...8.0 +6.5...8.1 +6.5...8.2 +6.5...8.25 +6.5...8.3 +6.5...8.4 +6.5...8.5 +6.5...8.6 +6.5...8.7 +6.5...8.8 +6.5...8.9 +6.5...9 +6.5...9.0 +6.5...9.2 +6.5...9.3 +6.5...9.5 +6.5...9.7 +6.5...9.8 +6.5...>10 +6.5...>10.0 +6.5...>11 +6.5...>11.0 +6.5...>12.0 +6.5...>7.0 +6.5...>7.9 +6.5...>8.0 +6.5...>8.3 +6.5...>8.5 +6.5...>8.7 +6.5...>8.8 +6.5...>9.0 +6.5...>9.5 +6.51 +6.55 +6.6 +6.6... +6.6...7.0 +6.6...7.1 +6.6...7.3 +6.6...7.4 +6.6...7.5 +6.6...7.9 +6.6...8.3 +6.6...8.4 +6.6...8.5 +6.6...8.6 +6.6...8.7 +6.6...8.8 +6.6...8.9 +6.6...9.0 +6.6...9.4 +6.6...9.7 +6.6...9.8 +6.6...>10.0 +6.6...>10.3 +6.6...>11 +6.6...>9.0 +6.6...>9.5 +6.65...8.6 +6.67 +6.7 +6.7... +6.7...10.2 +6.7...11.5 +6.7...6.8 +6.7...6.9 +6.7...7.0 +6.7...7.3 +6.7...7.4 +6.7...7.5 +6.7...7.6 +6.7...7.8 +6.7...8.0 +6.7...8.1 +6.7...8.2 +6.7...8.3 +6.7...8.5 +6.7...8.6 +6.7...8.7 +6.7...8.8 +6.7...8.9 +6.7...9.0 +6.7...9.1 +6.7...9.2 +6.7...9.5 +6.7...9.7 +6.7...9.8 +6.7...>10 +6.7...>7.0 +6.7...>7.5 +6.7...>8.0 +6.7...>8.5 +6.7...>8.6 +6.7...>9 +6.7...>9.0 +6.7...>9.3 +6.74...8.0 +6.75 +6.75... +6.75...9.5 +6.75...>9 +6.75...>9.0 +6.75...>9.5 +6.76...8.10 +6.8 +6.8... +6.8...10 +6.8...10.0 +6.8...10.5 +6.8...6.9 +6.8...7.0 +6.8...7.1 +6.8...7.2 +6.8...7.3 +6.8...7.5 +6.8...7.6 +6.8...7.7 +6.8...7.8 +6.8...7.9 +6.8...8.0 +6.8...8.2 +6.8...8.25 +6.8...8.3 +6.8...8.5 +6.8...8.6 +6.8...8.7 +6.8...8.8 +6.8...8.9 +6.8...9.0 +6.8...9.1 +6.8...9.3 +6.8...9.4 +6.8...9.5 +6.8...9.6 +6.8...9.9 +6.8...>10.0 +6.8...>7.9 +6.8...>8.0 +6.8...>8.1 +6.8...>8.5 +6.8...>9.0 +6.8...>9.1 +6.80...>8.5 +6.81...7.53 +6.85 +6.86 +6.88 +6.9 +6.9... +6.9...10.4 +6.9...12.2 +6.9...7.0 +6.9...7.1 +6.9...7.3 +6.9...7.6 +6.9...7.9 +6.9...8.0 +6.9...8.2 +6.9...8.4 +6.9...8.5 +6.9...8.6 +6.9...8.7 +6.9...8.8 +6.9...9.0 +6.9...9.1 +6.9...9.2 +6.9...9.5 +6.9...9.7 +6.9...>7.1 +6.9...>8 +6.9...>8.5 +6.9...>9 +6.9...>9.0 +6.9...>9.3 +6.9...>9.5 +6.9...>90 +7 +7...10 +7...10.5 +7...11 +7...7.5 +7...8 +7...8.5 +7...8.8 +7...9 +7...>10 +7...>10.5 +7...>9.5 +7.0 +7.0 +7.0... +7.0...10 +7.0...10.0 +7.0...10.2 +7.0...10.3 +7.0...10.5 +7.0...10.7 +7.0...11 +7.0...11.0 +7.0...11.5 +7.0...7.2 +7.0...7.2 +7.0...7.3 +7.0...7.4 +7.0...7.5 +7.0...7.6 +7.0...7.8 +7.0...7.9 +7.0...8.0 +7.0...8.1 +7.0...8.2 +7.0...8.3 +7.0...8.4 +7.0...8.5 +7.0...8.6 +7.0...8.67 +7.0...8.7 +7.0...8.8 +7.0...8.9 +7.0...9.0 +7.0...9.1 +7.0...9.2 +7.0...9.3 +7.0...9.4 +7.0...9.5 +7.0...9.7 +7.0...9.75 +7.0...9.8 +7.0...9.9 +7.0...<8.0 +7.0...>10 +7.0...>10.0 +7.0...>10.5 +7.0...>11 +7.0...>11.5 +7.0...>7.8 +7.0...>8.5 +7.0...>8.7 +7.0...>9 +7.0...>9.0 +7.0...>9.5 +7.00 +7.01 +7.03 +7.05 +7.07 +7.1 +7.1...10.1 +7.1...10.3 +7.1...7.9 +7.1...8.1 +7.1...8.2 +7.1...8.3 +7.1...8.4 +7.1...8.6 +7.1...8.7 +7.1...8.9 +7.1...9.0 +7.1...9.2 +7.1...9.3 +7.1...9.4 +7.1...9.8 +7.1...>8.3 +7.1...>8.5 +7.1...>9.0 +7.1...>9.5 +7.10 +7.15 +7.15...8.3 +7.2 +7.2...10.0 +7.2...10.2 +7.2...10.5 +7.2...13.5 +7.2...7.3 +7.2...7.4 +7.2...7.5 +7.2...7.6 +7.2...7.8 +7.2...8.0 +7.2...8.2 +7.2...8.3 +7.2...8.6 +7.2...8.7 +7.2...8.8 +7.2...8.9 +7.2...9.0 +7.2...9.1 +7.2...9.2 +7.2...9.3 +7.2...9.5 +7.2...9.6 +7.2...9.7 +7.2...9.8 +7.2...>10 +7.2...>10.0 +7.2...>11 +7.2...>8.0 +7.2...>8.5 +7.2...>8.7 +7.2...>9.0 +7.2...>9.1 +7.2...>9.2 +7.2...>9.5 +7.24 +7.25 +7.25...7.75 +7.25...8.1 +7.25...8.25 +7.25...8.4 +7.25...8.6 +7.25...8.7 +7.25...9.25 +7.25...>10.0 +7.25...>8.0 +7.25...>8.25 +7.25...>9.0 +7.26 +7.3 +7.3... +7.3...10.2 +7.3...10.5 +7.3...11 +7.3...7.5 +7.3...7.6 +7.3...7.8 +7.3...7.9 +7.3...8.0 +7.3...8.2 +7.3...8.3 +7.3...8.4 +7.3...8.5 +7.3...8.6 +7.3...8.8 +7.3...8.9 +7.3...9.0 +7.3...9.15 +7.3...9.2 +7.3...9.4 +7.3...9.5 +7.3...9.8 +7.3...9.9 +7.3...>10 +7.3...>10.0 +7.3...>10.5 +7.3...>7.8 +7.3...>8.0 +7.3...>8.3 +7.3...>9.0 +7.3...>9.2 +7.3...>9.3 +7.3...>9.5 +7.3...>9.75 +7.3...>90 +7.32 +7.35 +7.4 +7.4... +7.4...10 +7.4...10.0 +7.4...12.1 +7.4...7.6 +7.4...7.8 +7.4...8.0 +7.4...8.2 +7.4...8.3 +7.4...8.4 +7.4...8.5 +7.4...8.6 +7.4...8.7 +7.4...8.8 +7.4...9.0 +7.4...9.2 +7.4...9.3 +7.4...9.6 +7.4...9.7 +7.4...9.8 +7.4...>10.0 +7.4...>8 +7.4...>8.5 +7.4...>8.6 +7.4...>8.7 +7.4...>9.0 +7.45 +7.5 +7.5 +7.5... +7.5...10 +7.5...10.0 +7.5...10.1 +7.5...10.2 +7.5...10.3 +7.5...10.5 +7.5...10.8 +7.5...11 +7.5...11.0 +7.5...11.5 +7.5...12.0 +7.5...7.6 +7.5...7.8 +7.5...8 +7.5...8.0 +7.5...8.1 +7.5...8.2 +7.5...8.4 +7.5...8.5 +7.5...8.6 +7.5...8.7 +7.5...9.0 +7.5...9.1 +7.5...9.2 +7.5...9.3 +7.5...9.4 +7.5...9.5 +7.5...9.6 +7.5...9.7 +7.5...9.8 +7.5...>10 +7.5...>10.0 +7.5...>10.5 +7.5...>11.0 +7.5...>8.3 +7.5...>8.5 +7.5...>8.7 +7.5...>8.75 +7.5...>9 +7.5...>9.0 +7.5...>9.2 +7.5...>9.5 +7.54 +7.55 +7.6 +7.6 +7.6...10.3 +7.6...10.5 +7.6...7.8 +7.6...7.9 +7.6...8.0 +7.6...8.2 +7.6...8.3 +7.6...8.4 +7.6...8.5 +7.6...8.6 +7.6...8.8 +7.6...9.0 +7.6...9.2 +7.6...9.3 +7.6...9.4 +7.6...9.5 +7.6...9.7 +7.6...>10.0 +7.6...>10.3 +7.6...>10.5 +7.6...>11 +7.6...>8.25 +7.6...>8.8 +7.6...>9.0 +7.6...>9.5 +7.65 +7.7... +7.7...10 +7.7...10.0 +7.7...10.3 +7.7...10.5 +7.7...11.0 +7.7...11.5 +7.7...7.8 +7.7...8.0 +7.7...8.3 +7.7...8.5 +7.7...8.7 +7.7...9.0 +7.7...9.25 +7.7...9.4 +7.7...9.5 +7.7...9.8 +7.7...>10.5 +7.7...>8.5 +7.7...>8.6 +7.7...>9.0 +7.7...>9.5 +7.72...8.7 +7.75 +7.75... +7.75...8.1 +7.78 +7.8 +7.8...10.2 +7.8...7.9 +7.8...8.0 +7.8...8.1 +7.8...8.2 +7.8...8.4 +7.8...8.5 +7.8...8.7 +7.8...8.8 +7.8...8.9 +7.8...9.0 +7.8...9.2 +7.8...9.3 +7.8...9.4 +7.8...9.6 +7.8...<9.8 +7.8...>10.0 +7.8...>8.8 +7.8...>8.9 +7.8...>9.0 +7.8...>9.1 +7.8...>9.4 +7.80 +7.85 +7.9 +7.9...10.9 +7.9...8.1 +7.9...8.2 +7.9...8.3 +7.9...8.5 +7.9...8.6 +7.9...8.9 +7.9...9.0 +7.9...9.3 +7.96 +8 +8...10 +8...10.2 +8...10.5 +8...11.0 +8...8.5 +8...9 +8...>10 +8...>11 +8.0 +8.0...10 +8.0...10.0 +8.0...10.2 +8.0...10.3 +8.0...10.5 +8.0...10.8 +8.0...11.0 +8.0...11.2 +8.0...11.7 +8.0...12.0 +8.0...8.5 +8.0...8.12 +8.0...8.2 +8.0...8.4 +8.0...8.5 +8.0...8.6 +8.0...8.7 +8.0...8.8 +8.0...8.9 +8.0...9.0 +8.0...9.2 +8.0...9.4 +8.0...9.5 +8.0...9.7 +8.0...>10 +8.0...>10.0 +8.0...>10.5 +8.0...>11 +8.0...>13.0 +8.0...>8.75 +8.0...>9.0 +8.0...>9.2 +8.0...>9.5 +8.1 +8.1...10.5 +8.1...10.9 +8.1...8.2 +8.1...8.3 +8.1...8.4 +8.1...8.6 +8.1...8.7 +8.1...8.75 +8.1...8.9 +8.1...9.1 +8.1...9.9 +8.1...>9.5 +8.13 +8.15 +8.2 +8.2... +8.2...10.2 +8.2...10.4 +8.2...8.4 +8.2...8.5 +8.2...8.8 +8.2...8.9 +8.2...9.0 +8.2...9.6 +8.2...9.8 +8.2...>10 +8.2...>10.5 +8.2...>11 +8.2...>11.0 +8.2...>8.8 +8.2...>9.3 +8.20 +8.25 +8.25...10.2 +8.27 +8.27...10 +8.28 +8.3 +8.3... +8.3...10.2 +8.3...10.3 +8.3...10.8 +8.3...8.4 +8.3...8.5 +8.3...8.6 +8.3...8.8 +8.3...9.6 +8.3...9.9 +8.3...>9.5 +8.3...>9.8 +8.35 +8.4 +8.4...10.1 +8.4...8.5 +8.4...8.6 +8.4...8.7 +8.4...8.8 +8.4...8.9 +8.4...9.0 +8.4...9.2 +8.4...9.5 +8.4...<9.8 +8.4...>10.0 +8.4...>10.5 +8.4...>9.8 +8.48 +8.5 +8.5... +8.5...10.0 +8.5...10.3 +8.5...10.5 +8.5...10.7 +8.5...10.8 +8.5...11 +8.5...11.0 +8.5...12.5 +8.5...8.6 +8.5...8.8 +8.5...9.0 +8.5...9.1 +8.5...9.2 +8.5...9.3 +8.5...9.4 +8.5...9.5 +8.5...9.9 +8.5...>10 +8.5...>11 +8.5...>11.5 +8.5...>9.5 +8.6 +8.6...10.2 +8.6...10.3 +8.6...11 +8.6...8.7 +8.6...8.8 +8.6...8.9 +8.6...9.4 +8.6...>11 +8.6...>99 +8.65 +8.7 +8.7...10.6 +8.7...11.2 +8.7...11.3 +8.7...11.7 +8.7...8.9 +8.7...9.1 +8.7...9.6 +8.7...9.8 +8.75 +8.8 +8.8...10.3 +8.8...10.7 +8.8...9.0 +8.8...9.2 +8.8...9.8 +8.8...>9.8 +8.9 +8.9...10.3 +8.9...10.4 +8.9...10.9 +8.9...11.5 +8.9...9.2 +9 +9.8 +9...10 +9...11 +9...>12 +9.0 +9.0... +9.0...10 +9.0...10.0 +9.0...10.5 +9.0...10.7 +9.0...11 +9.0...11.0 +9.0...11.1 +9.0...11.2 +9.0...11.3 +9.0...11.5 +9.0...12 +9.0...9.2 +9.0...9.5 +9.0...>10.7 +9.0...>11.0 +9.1 +9.1...10 +9.1...10.1 +9.1...9.5 +9.15 +9.2 +9.2...10 +9.2...10.8 +9.2...12 +9.2...9.3 +9.2...9.4 +9.2...9.5 +9.2...9.6 +9.25 +9.3 +9.4 +9.4...10 +9.4...12.2 +9.4...9.7 +9.5 +9.5... +9.5...10 +9.5...10.0 +9.5...10.4 +9.5...10.5 +9.5...10.6 +9.5...11.2 +9.5...9.8 +9.5...>10.2 +9.5...>10.5 +9.55 +9.6 +9.6...10 +9.6...10.2 +9.6...11.5 +9.6...>11.2 +9.63 +9.7 +9.7...11 +9.7...11.5 +9.7...9.8 +9.7...>12 +9.75 +9.76 +9.8 +9.8...10.0 +9.8...10.1 +9.8...>12.5 +9.9 +9.99 +10 +10...10.5 +10...11 +10.0 +10.0...10.4 +10.0...10.5 +10.0...11.25 +10.0...11.5 +10.0...12.5 +10.0...>12.5 +10.2 +10.2...11.8 +10.25 +10.3 +10.32 +10.4 +10.45 +10.5 +10.5...11.0 +10.5...11.5 +10.5...<13.5 +10.6 +10.7 +10.7...12.3 +10.70 +10.75 +10.8 +11 +11 +11.0 +11.3 +11.5 +11.5...12.5 +11.75 +12 +12.0 +12.2 +14 +15 +16 +16.7 +17 +18 +19 +19.8 +20 +20.0 +22 +22 +22.9 +23 +23...25 +23.7 +24 +24.0 +\N diff --git a/contrib/seg/expected/security.out b/contrib/seg/expected/security.out new file mode 100644 index 0000000..b47598d --- /dev/null +++ b/contrib/seg/expected/security.out @@ -0,0 +1,32 @@ +-- +-- Test extension script protection against search path overriding +-- +CREATE ROLE regress_seg_role; +SELECT current_database() AS datname \gset +GRANT CREATE ON DATABASE :"datname" TO regress_seg_role; +SET ROLE regress_seg_role; +CREATE SCHEMA regress_seg_schema; +CREATE FUNCTION regress_seg_schema.exfun(i int) RETURNS int AS $$ +BEGIN + CREATE EXTENSION seg VERSION '1.2'; + + CREATE FUNCTION regress_seg_schema.compare(oid, regclass) RETURNS boolean AS + 'BEGIN RAISE EXCEPTION ''overloaded compare() called by %'', current_user; END;' LANGUAGE plpgsql; + + CREATE OPERATOR = (LEFTARG = oid, RIGHTARG = regclass, PROCEDURE = regress_seg_schema.compare); + + ALTER EXTENSION seg UPDATE TO '1.3'; + + RETURN i; +END; $$ LANGUAGE plpgsql; +CREATE SCHEMA test_schema +CREATE TABLE t(i int) PARTITION BY RANGE (i) +CREATE TABLE p1 PARTITION OF t FOR VALUES FROM (1) TO (regress_seg_schema.exfun(2)); +DROP SCHEMA test_schema CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to table test_schema.t +drop cascades to extension seg +drop cascades to operator test_schema.=(oid,regclass) +RESET ROLE; +DROP OWNED BY regress_seg_role; +DROP ROLE regress_seg_role; diff --git a/contrib/seg/expected/seg.out b/contrib/seg/expected/seg.out new file mode 100644 index 0000000..2320464 --- /dev/null +++ b/contrib/seg/expected/seg.out @@ -0,0 +1,1275 @@ +-- +-- Test seg datatype +-- +CREATE EXTENSION seg; +-- Check whether any of our opclasses fail amvalidate +SELECT amname, opcname +FROM pg_opclass opc LEFT JOIN pg_am am ON am.oid = opcmethod +WHERE opc.oid >= 16384 AND NOT amvalidate(opc.oid); + amname | opcname +--------+--------- +(0 rows) + +-- +-- testing the input and output functions +-- +-- Any number +SELECT '1'::seg AS seg; + seg +----- + 1 +(1 row) + +SELECT '-1'::seg AS seg; + seg +----- + -1 +(1 row) + +SELECT '1.0'::seg AS seg; + seg +----- + 1.0 +(1 row) + +SELECT '-1.0'::seg AS seg; + seg +------ + -1.0 +(1 row) + +SELECT '1e7'::seg AS seg; + seg +------- + 1e+07 +(1 row) + +SELECT '-1e7'::seg AS seg; + seg +-------- + -1e+07 +(1 row) + +SELECT '1.0e7'::seg AS seg; + seg +--------- + 1.0e+07 +(1 row) + +SELECT '-1.0e7'::seg AS seg; + seg +---------- + -1.0e+07 +(1 row) + +SELECT '1e+7'::seg AS seg; + seg +------- + 1e+07 +(1 row) + +SELECT '-1e+7'::seg AS seg; + seg +-------- + -1e+07 +(1 row) + +SELECT '1.0e+7'::seg AS seg; + seg +--------- + 1.0e+07 +(1 row) + +SELECT '-1.0e+7'::seg AS seg; + seg +---------- + -1.0e+07 +(1 row) + +SELECT '1e-7'::seg AS seg; + seg +------- + 1e-07 +(1 row) + +SELECT '-1e-7'::seg AS seg; + seg +-------- + -1e-07 +(1 row) + +SELECT '1.0e-7'::seg AS seg; + seg +--------- + 1.0e-07 +(1 row) + +SELECT '-1.0e-7'::seg AS seg; + seg +---------- + -1.0e-07 +(1 row) + +SELECT '2e-6'::seg AS seg; + seg +------- + 2e-06 +(1 row) + +SELECT '2e-5'::seg AS seg; + seg +------- + 2e-05 +(1 row) + +SELECT '2e-4'::seg AS seg; + seg +-------- + 0.0002 +(1 row) + +SELECT '2e-3'::seg AS seg; + seg +------- + 0.002 +(1 row) + +SELECT '2e-2'::seg AS seg; + seg +------ + 0.02 +(1 row) + +SELECT '2e-1'::seg AS seg; + seg +----- + 0.2 +(1 row) + +SELECT '2e-0'::seg AS seg; + seg +----- + 2 +(1 row) + +SELECT '2e+0'::seg AS seg; + seg +----- + 2 +(1 row) + +SELECT '2e+1'::seg AS seg; + seg +----- + 2e1 +(1 row) + +SELECT '2e+2'::seg AS seg; + seg +----- + 2e2 +(1 row) + +SELECT '2e+3'::seg AS seg; + seg +----- + 2e3 +(1 row) + +SELECT '2e+4'::seg AS seg; + seg +----- + 2e4 +(1 row) + +SELECT '2e+5'::seg AS seg; + seg +------- + 2e+05 +(1 row) + +SELECT '2e+6'::seg AS seg; + seg +------- + 2e+06 +(1 row) + +-- Significant digits preserved +SELECT '1'::seg AS seg; + seg +----- + 1 +(1 row) + +SELECT '1.0'::seg AS seg; + seg +----- + 1.0 +(1 row) + +SELECT '1.00'::seg AS seg; + seg +------ + 1.00 +(1 row) + +SELECT '1.000'::seg AS seg; + seg +------- + 1.000 +(1 row) + +SELECT '1.0000'::seg AS seg; + seg +-------- + 1.0000 +(1 row) + +SELECT '1.00000'::seg AS seg; + seg +--------- + 1.00000 +(1 row) + +SELECT '1.000000'::seg AS seg; + seg +--------- + 1.00000 +(1 row) + +SELECT '0.000000120'::seg AS seg; + seg +---------- + 1.20e-07 +(1 row) + +SELECT '3.400e5'::seg AS seg; + seg +----------- + 3.400e+05 +(1 row) + +-- Digits truncated +SELECT '12.34567890123456'::seg AS seg; + seg +--------- + 12.3457 +(1 row) + +-- Same, with a very long input +SELECT '12.3456789012345600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'::seg AS seg; + seg +--------- + 12.3457 +(1 row) + +-- Numbers with certainty indicators +SELECT '~6.5'::seg AS seg; + seg +------ + ~6.5 +(1 row) + +SELECT '<6.5'::seg AS seg; + seg +------ + <6.5 +(1 row) + +SELECT '>6.5'::seg AS seg; + seg +------ + >6.5 +(1 row) + +SELECT '~ 6.5'::seg AS seg; + seg +------ + ~6.5 +(1 row) + +SELECT '< 6.5'::seg AS seg; + seg +------ + <6.5 +(1 row) + +SELECT '> 6.5'::seg AS seg; + seg +------ + >6.5 +(1 row) + +-- Open intervals +SELECT '0..'::seg AS seg; + seg +------ + 0 .. +(1 row) + +SELECT '0...'::seg AS seg; + seg +------ + 0 .. +(1 row) + +SELECT '0 ..'::seg AS seg; + seg +------ + 0 .. +(1 row) + +SELECT '0 ...'::seg AS seg; + seg +------ + 0 .. +(1 row) + +SELECT '..0'::seg AS seg; + seg +------ + .. 0 +(1 row) + +SELECT '...0'::seg AS seg; + seg +------ + .. 0 +(1 row) + +SELECT '.. 0'::seg AS seg; + seg +------ + .. 0 +(1 row) + +SELECT '... 0'::seg AS seg; + seg +------ + .. 0 +(1 row) + +-- Finite intervals +SELECT '0 .. 1'::seg AS seg; + seg +-------- + 0 .. 1 +(1 row) + +SELECT '-1 .. 0'::seg AS seg; + seg +--------- + -1 .. 0 +(1 row) + +SELECT '-1 .. 1'::seg AS seg; + seg +--------- + -1 .. 1 +(1 row) + +-- (+/-) intervals +SELECT '0(+-)1'::seg AS seg; + seg +--------- + -1 .. 1 +(1 row) + +SELECT '0(+-)1.0'::seg AS seg; + seg +------------- + -1.0 .. 1.0 +(1 row) + +SELECT '1.0(+-)0.005'::seg AS seg; + seg +---------------- + 0.995 .. 1.005 +(1 row) + +SELECT '101(+-)1'::seg AS seg; + seg +------------------ + 1.00e2 .. 1.02e2 +(1 row) + +-- incorrect number of significant digits in 99.0: +SELECT '100(+-)1'::seg AS seg; + seg +---------------- + 99.0 .. 1.01e2 +(1 row) + +-- invalid input +SELECT ''::seg AS seg; +ERROR: bad seg representation +LINE 1: SELECT ''::seg AS seg; + ^ +DETAIL: syntax error at end of input +SELECT 'ABC'::seg AS seg; +ERROR: bad seg representation +LINE 1: SELECT 'ABC'::seg AS seg; + ^ +DETAIL: syntax error at or near "A" +SELECT '1ABC'::seg AS seg; +ERROR: bad seg representation +LINE 1: SELECT '1ABC'::seg AS seg; + ^ +DETAIL: syntax error at or near "A" +SELECT '1.'::seg AS seg; +ERROR: bad seg representation +LINE 1: SELECT '1.'::seg AS seg; + ^ +DETAIL: syntax error at or near "." +SELECT '1.....'::seg AS seg; +ERROR: bad seg representation +LINE 1: SELECT '1.....'::seg AS seg; + ^ +DETAIL: syntax error at or near ".." +SELECT '.1'::seg AS seg; +ERROR: bad seg representation +LINE 1: SELECT '.1'::seg AS seg; + ^ +DETAIL: syntax error at or near "." +SELECT '1..2.'::seg AS seg; +ERROR: bad seg representation +LINE 1: SELECT '1..2.'::seg AS seg; + ^ +DETAIL: syntax error at or near "." +SELECT '1 e7'::seg AS seg; +ERROR: bad seg representation +LINE 1: SELECT '1 e7'::seg AS seg; + ^ +DETAIL: syntax error at or near "e" +SELECT '1e700'::seg AS seg; +ERROR: "1e700" is out of range for type real +LINE 1: SELECT '1e700'::seg AS seg; + ^ +-- +-- testing the operators +-- +-- equality/inequality: +-- +SELECT '24 .. 33.20'::seg = '24 .. 33.20'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '24 .. 33.20'::seg = '24 .. 33.21'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '24 .. 33.20'::seg != '24 .. 33.20'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '24 .. 33.20'::seg != '24 .. 33.21'::seg AS bool; + bool +------ + t +(1 row) + +-- overlap +-- +SELECT '1'::seg && '1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '1'::seg && '2'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '0 ..'::seg && '0 ..'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0 .. 1'::seg && '0 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '..0'::seg && '0..'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '-1 .. 0.1'::seg && '0 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '-1 .. 0'::seg && '0 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '-1 .. -0.0001'::seg && '0 .. 1'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '0 ..'::seg && '1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0 .. 1'::seg && '1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0 .. 1'::seg && '2'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '0 .. 2'::seg && '1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '1'::seg && '0 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '2'::seg && '0 .. 1'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '1'::seg && '0 .. 2'::seg AS bool; + bool +------ + t +(1 row) + +-- overlap on the left +-- +SELECT '1'::seg &< '0'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '1'::seg &< '1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '1'::seg &< '2'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0 .. 1'::seg &< '0'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '0 .. 1'::seg &< '1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0 .. 1'::seg &< '2'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0 .. 1'::seg &< '0 .. 0.5'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '0 .. 1'::seg &< '0 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0 .. 1'::seg &< '0 .. 2'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0 .. 1'::seg &< '1 .. 2'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0 .. 1'::seg &< '2 .. 3'::seg AS bool; + bool +------ + t +(1 row) + +-- overlap on the right +-- +SELECT '0'::seg &> '1'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '1'::seg &> '1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '2'::seg &> '1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0'::seg &> '0 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '1'::seg &> '0 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '2'::seg &> '0 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0 .. 0.5'::seg &> '0 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0 .. 1'::seg &> '0 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0 .. 2'::seg &> '0 .. 2'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '1 .. 2'::seg &> '0 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '2 .. 3'::seg &> '0 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +-- left +-- +SELECT '1'::seg << '0'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '1'::seg << '1'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '1'::seg << '2'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0 .. 1'::seg << '0'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '0 .. 1'::seg << '1'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '0 .. 1'::seg << '2'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0 .. 1'::seg << '0 .. 0.5'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '0 .. 1'::seg << '0 .. 1'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '0 .. 1'::seg << '0 .. 2'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '0 .. 1'::seg << '1 .. 2'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '0 .. 1'::seg << '2 .. 3'::seg AS bool; + bool +------ + t +(1 row) + +-- right +-- +SELECT '0'::seg >> '1'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '1'::seg >> '1'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '2'::seg >> '1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0'::seg >> '0 .. 1'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '1'::seg >> '0 .. 1'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '2'::seg >> '0 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0 .. 0.5'::seg >> '0 .. 1'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '0 .. 1'::seg >> '0 .. 1'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '0 .. 2'::seg >> '0 .. 2'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '1 .. 2'::seg >> '0 .. 1'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '2 .. 3'::seg >> '0 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +-- "contained in" (the left value belongs within the interval specified in the right value): +-- +SELECT '0'::seg <@ '0'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0'::seg <@ '0 ..'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0'::seg <@ '.. 0'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0'::seg <@ '-1 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0'::seg <@ '-1 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '-1'::seg <@ '-1 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '1'::seg <@ '-1 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '-1 .. 1'::seg <@ '-1 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +-- "contains" (the left value contains the interval specified in the right value): +-- +SELECT '0'::seg @> '0'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '0 .. '::seg <@ '0'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '.. 0'::seg <@ '0'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '-1 .. 1'::seg <@ '0'::seg AS bool; + bool +------ + f +(1 row) + +SELECT '0'::seg <@ '-1 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '-1'::seg <@ '-1 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +SELECT '1'::seg <@ '-1 .. 1'::seg AS bool; + bool +------ + t +(1 row) + +-- Load some example data and build the index +-- +CREATE TABLE test_seg (s seg); +\copy test_seg from 'data/test_seg.data' +CREATE INDEX test_seg_ix ON test_seg USING gist (s); +SET enable_indexscan = false; +EXPLAIN (COSTS OFF) +SELECT count(*) FROM test_seg WHERE s @> '11..11.3'; + QUERY PLAN +------------------------------------------------------- + Aggregate + -> Bitmap Heap Scan on test_seg + Recheck Cond: (s @> '1.1e1 .. 11.3'::seg) + -> Bitmap Index Scan on test_seg_ix + Index Cond: (s @> '1.1e1 .. 11.3'::seg) +(5 rows) + +SELECT count(*) FROM test_seg WHERE s @> '11..11.3'; + count +------- + 143 +(1 row) + +RESET enable_indexscan; +SET enable_bitmapscan = false; +EXPLAIN (COSTS OFF) +SELECT count(*) FROM test_seg WHERE s @> '11..11.3'; + QUERY PLAN +----------------------------------------------------- + Aggregate + -> Index Only Scan using test_seg_ix on test_seg + Index Cond: (s @> '1.1e1 .. 11.3'::seg) +(3 rows) + +SELECT count(*) FROM test_seg WHERE s @> '11..11.3'; + count +------- + 143 +(1 row) + +RESET enable_bitmapscan; +-- Test sorting +SELECT * FROM test_seg WHERE s @> '11..11.3' GROUP BY s; + s +----------------- + .. 4.0e1 + .. >8.2e1 + .. 9.0e1 + <1.0 .. >13.0 + 1.3 .. 12.0 + 2.0 .. 11.5 + 2.1 .. 11.8 + <2.3 .. + >2.3 .. + 2.4 .. 11.3 + 2.5 .. 11.5 + 2.5 .. 11.8 + 2.6 .. + 2.7 .. 12.0 + <3.0 .. + 3 .. 5.8e1 + 3.1 .. 11.5 + 3.5 .. 11.5 + 3.5 .. 12.2 + <4.0 .. >1.2e1 + <4.0 .. + 4 .. 1.2e1 + 4.0 .. 11.7 + 4.0 .. 12.5 + 4.0 .. 13.0 + 4.0 .. 6.0e1 + 4.0 .. + 4.2 .. 11.5 + 4.2 .. 11.7 + <4.5 .. >1.2e1 + 4.5 .. 11.5 + 4.5 .. <1.2e1 + 4.5 .. >1.2e1 + 4.5 .. 12.5 + 4.5 .. 1.15e2 + 4.7 .. 11.8 + 4.8 .. 11.5 + 4.8 .. 11.6 + 4.8 .. 12.5 + 4.8 .. + 4.9 .. >1.2e1 + 4.9 .. + 5 .. 11.5 + 5 .. 1.2e1 + 5 .. 3.0e1 + 5.0 .. 11.4 + 5.0 .. 11.5 + 5.0 .. 11.6 + 5.0 .. 11.7 + 5.0 .. 12.0 + 5.0 .. >12.0 + 5.0 .. >1.2e1 + 5.2 .. 11.5 + 5.2 .. >1.2e1 + 5.25 .. >1.2e1 + 5.3 .. 11.5 + 5.3 .. 1.3e1 + 5.3 .. >9.0e1 + 5.3 .. + 5.4 .. + 5.5 .. 11.5 + 5.5 .. 11.7 + 5.5 .. 1.2e1 + 5.5 .. >1.2e1 + 5.5 .. 12.5 + 5.5 .. 13.5 + 5.5 .. + >5.5 .. + 5.7 .. + 5.9 .. + 6 .. 11.5 + 6 .. >1.2e1 + 6.0 .. 11.5 + 6.0 .. 1.3e1 + >6.0 .. <11.5 + 6.1 .. >1.2e1 + 6.1 .. + 6.2 .. >11.5 + 6.3 .. + 6.5 .. 11.5 + 6.5 .. 12.0 + 6.5 .. >12.0 + 6.5 .. + 6.6 .. + 6.7 .. 11.5 + 6.7 .. + 6.75 .. + 6.8 .. + 6.9 .. 12.2 + 6.9 .. >9.0e1 + 6.9 .. + <7.0 .. >11.5 + 7.0 .. 11.5 + 7.0 .. >11.5 + 7.0 .. + >7.15 .. + 7.2 .. 13.5 + 7.3 .. >9.0e1 + 7.3 .. + >7.3 .. + 7.4 .. 12.1 + 7.4 .. + 7.5 .. 11.5 + 7.5 .. 12.0 + 7.5 .. + 7.7 .. 11.5 + 7.7 .. + 7.75 .. + 8.0 .. 11.7 + 8.0 .. 12.0 + 8.0 .. >13.0 + 8.2 .. + 8.3 .. + 8.5 .. >11.5 + 8.5 .. 12.5 + 8.5 .. + 8.6 .. >9.9e1 + 8.7 .. 11.3 + 8.7 .. 11.7 + 8.9 .. 11.5 + 9 .. >1.2e1 + 9.0 .. 11.3 + 9.0 .. 11.5 + 9.0 .. 1.2e1 + 9.0 .. + 9.2 .. 1.2e1 + 9.4 .. 12.2 + <9.5 .. 1.2e1 + <9.5 .. >12.2 + 9.5 .. + 9.6 .. 11.5 + 9.7 .. 11.5 + 9.7 .. >1.2e1 + 9.8 .. >12.5 + <1.0e1 .. >11.6 + 10.0 .. 11.5 + 10.0 .. 12.5 + 10.0 .. >12.5 + 10.2 .. 11.8 + <10.5 .. 11.5 + 10.5 .. 11.5 + 10.5 .. <13.5 + 10.7 .. 12.3 +(143 rows) + +-- Test functions +SELECT seg_lower(s), seg_center(s), seg_upper(s) +FROM test_seg WHERE s @> '11.2..11.3' OR s IS NULL ORDER BY s; + seg_lower | seg_center | seg_upper +-----------+------------+----------- + -Infinity | -Infinity | 40 + -Infinity | -Infinity | 82 + -Infinity | -Infinity | 90 + 1 | 7 | 13 + 1.3 | 6.65 | 12 + 2 | 6.75 | 11.5 + 2.1 | 6.95 | 11.8 + 2.3 | Infinity | Infinity + 2.3 | Infinity | Infinity + 2.4 | 6.8500004 | 11.3 + 2.5 | 7 | 11.5 + 2.5 | 7.15 | 11.8 + 2.6 | Infinity | Infinity + 2.7 | 7.35 | 12 + 3 | Infinity | Infinity + 3 | 30.5 | 58 + 3.1 | 7.3 | 11.5 + 3.5 | 7.5 | 11.5 + 3.5 | 7.85 | 12.2 + 4 | 8 | 12 + 4 | Infinity | Infinity + 4 | 8 | 12 + 4 | 7.85 | 11.7 + 4 | 8.25 | 12.5 + 4 | 8.5 | 13 + 4 | 32 | 60 + 4 | Infinity | Infinity + 4.2 | 7.85 | 11.5 + 4.2 | 7.95 | 11.7 + 4.5 | 8.25 | 12 + 4.5 | 8 | 11.5 + 4.5 | 8.25 | 12 + 4.5 | 8.25 | 12 + 4.5 | 8.5 | 12.5 + 4.5 | 59.75 | 115 + 4.7 | 8.25 | 11.8 + 4.8 | 8.15 | 11.5 + 4.8 | 8.200001 | 11.6 + 4.8 | 8.65 | 12.5 + 4.8 | Infinity | Infinity + 4.9 | 8.45 | 12 + 4.9 | Infinity | Infinity + 5 | 8.25 | 11.5 + 5 | 8.5 | 12 + 5 | 17.5 | 30 + 5 | 8.2 | 11.4 + 5 | 8.25 | 11.5 + 5 | 8.3 | 11.6 + 5 | 8.35 | 11.7 + 5 | 8.5 | 12 + 5 | 8.5 | 12 + 5 | 8.5 | 12 + 5.2 | 8.35 | 11.5 + 5.2 | 8.6 | 12 + 5.25 | 8.625 | 12 + 5.3 | 8.4 | 11.5 + 5.3 | 9.15 | 13 + 5.3 | 47.65 | 90 + 5.3 | Infinity | Infinity + 5.4 | Infinity | Infinity + 5.5 | 8.5 | 11.5 + 5.5 | 8.6 | 11.7 + 5.5 | 8.75 | 12 + 5.5 | 8.75 | 12 + 5.5 | 9 | 12.5 + 5.5 | 9.5 | 13.5 + 5.5 | Infinity | Infinity + 5.5 | Infinity | Infinity + 5.7 | Infinity | Infinity + 5.9 | Infinity | Infinity + 6 | 8.75 | 11.5 + 6 | 9 | 12 + 6 | 8.75 | 11.5 + 6 | 9.5 | 13 + 6 | 8.75 | 11.5 + 6.1 | 9.05 | 12 + 6.1 | Infinity | Infinity + 6.2 | 8.85 | 11.5 + 6.3 | Infinity | Infinity + 6.5 | 9 | 11.5 + 6.5 | 9.25 | 12 + 6.5 | 9.25 | 12 + 6.5 | Infinity | Infinity + 6.6 | Infinity | Infinity + 6.7 | 9.1 | 11.5 + 6.7 | Infinity | Infinity + 6.75 | Infinity | Infinity + 6.8 | Infinity | Infinity + 6.9 | 9.55 | 12.2 + 6.9 | 48.45 | 90 + 6.9 | Infinity | Infinity + 7 | 9.25 | 11.5 + 7 | 9.25 | 11.5 + 7 | 9.25 | 11.5 + 7 | Infinity | Infinity + 7.15 | Infinity | Infinity + 7.2 | 10.35 | 13.5 + 7.3 | 48.65 | 90 + 7.3 | Infinity | Infinity + 7.3 | Infinity | Infinity + 7.4 | 9.75 | 12.1 + 7.4 | Infinity | Infinity + 7.5 | 9.5 | 11.5 + 7.5 | 9.75 | 12 + 7.5 | Infinity | Infinity + 7.7 | 9.6 | 11.5 + 7.7 | Infinity | Infinity + 7.75 | Infinity | Infinity + 8 | 9.85 | 11.7 + 8 | 10 | 12 + 8 | 10.5 | 13 + 8.2 | Infinity | Infinity + 8.3 | Infinity | Infinity + 8.5 | 10 | 11.5 + 8.5 | 10.5 | 12.5 + 8.5 | Infinity | Infinity + 8.6 | 53.8 | 99 + 8.7 | 10 | 11.3 + 8.7 | 10.2 | 11.7 + 8.9 | 10.2 | 11.5 + 9 | 10.5 | 12 + 9 | 10.15 | 11.3 + 9 | 10.25 | 11.5 + 9 | 10.5 | 12 + 9 | Infinity | Infinity + 9.2 | 10.6 | 12 + 9.4 | 10.799999 | 12.2 + 9.5 | 10.75 | 12 + 9.5 | 10.85 | 12.2 + 9.5 | Infinity | Infinity + 9.6 | 10.55 | 11.5 + 9.7 | 10.6 | 11.5 + 9.7 | 10.85 | 12 + 9.8 | 11.15 | 12.5 + 10 | 10.8 | 11.6 + 10 | 10.75 | 11.5 + 10 | 11.25 | 12.5 + 10 | 11.25 | 12.5 + 10.2 | 11 | 11.8 + 10.5 | 11 | 11.5 + 10.5 | 11 | 11.5 + 10.5 | 12 | 13.5 + 10.7 | 11.5 | 12.3 + | | +(144 rows) + diff --git a/contrib/seg/seg--1.0--1.1.sql b/contrib/seg/seg--1.0--1.1.sql new file mode 100644 index 0000000..ae6cb2f --- /dev/null +++ b/contrib/seg/seg--1.0--1.1.sql @@ -0,0 +1,63 @@ +/* contrib/seg/seg--1.0--1.1.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION seg UPDATE TO '1.1'" to load this file. \quit + +-- Update procedure signatures the hard way. +-- We use to_regprocedure() so that query doesn't fail if run against 9.6beta1 definitions, +-- wherein the signatures have been updated already. In that case to_regprocedure() will +-- return NULL and no updates will happen. +DO LANGUAGE plpgsql +$$ +DECLARE + my_schema pg_catalog.text := pg_catalog.quote_ident(pg_catalog.current_schema()); + old_path pg_catalog.text := pg_catalog.current_setting('search_path'); +BEGIN +-- for safety, transiently set search_path to just pg_catalog+pg_temp +PERFORM pg_catalog.set_config('search_path', 'pg_catalog, pg_temp', true); + +UPDATE pg_catalog.pg_proc SET + proargtypes = pg_catalog.array_to_string(newtypes::pg_catalog.oid[], ' ')::pg_catalog.oidvector, + pronargs = pg_catalog.array_length(newtypes, 1) +FROM (VALUES +(NULL::pg_catalog.text, NULL::pg_catalog.text[]), -- establish column types +('gseg_consistent(internal,SCH.seg,int4,oid,internal)', '{internal,SCH.seg,int2,oid,internal}') +) AS update_data (oldproc, newtypestext), +LATERAL ( + SELECT array_agg(replace(typ, 'SCH', my_schema)::regtype) as newtypes FROM unnest(newtypestext) typ +) ls +WHERE oid = to_regprocedure(my_schema || '.' || replace(oldproc, 'SCH', my_schema)); + +PERFORM pg_catalog.set_config('search_path', old_path, true); +END +$$; + +ALTER FUNCTION seg_in(cstring) PARALLEL SAFE; +ALTER FUNCTION seg_out(seg) PARALLEL SAFE; +ALTER FUNCTION seg_over_left(seg, seg) PARALLEL SAFE; +ALTER FUNCTION seg_over_right(seg, seg) PARALLEL SAFE; +ALTER FUNCTION seg_left(seg, seg) PARALLEL SAFE; +ALTER FUNCTION seg_right(seg, seg) PARALLEL SAFE; +ALTER FUNCTION seg_lt(seg, seg) PARALLEL SAFE; +ALTER FUNCTION seg_le(seg, seg) PARALLEL SAFE; +ALTER FUNCTION seg_gt(seg, seg) PARALLEL SAFE; +ALTER FUNCTION seg_ge(seg, seg) PARALLEL SAFE; +ALTER FUNCTION seg_contains(seg, seg) PARALLEL SAFE; +ALTER FUNCTION seg_contained(seg, seg) PARALLEL SAFE; +ALTER FUNCTION seg_overlap(seg, seg) PARALLEL SAFE; +ALTER FUNCTION seg_same(seg, seg) PARALLEL SAFE; +ALTER FUNCTION seg_different(seg, seg) PARALLEL SAFE; +ALTER FUNCTION seg_cmp(seg, seg) PARALLEL SAFE; +ALTER FUNCTION seg_union(seg, seg) PARALLEL SAFE; +ALTER FUNCTION seg_inter(seg, seg) PARALLEL SAFE; +ALTER FUNCTION seg_size(seg) PARALLEL SAFE; +ALTER FUNCTION seg_center(seg) PARALLEL SAFE; +ALTER FUNCTION seg_upper(seg) PARALLEL SAFE; +ALTER FUNCTION seg_lower(seg) PARALLEL SAFE; +ALTER FUNCTION gseg_consistent(internal, seg, smallint, oid, internal) PARALLEL SAFE; +ALTER FUNCTION gseg_compress(internal) PARALLEL SAFE; +ALTER FUNCTION gseg_decompress(internal) PARALLEL SAFE; +ALTER FUNCTION gseg_penalty(internal, internal, internal) PARALLEL SAFE; +ALTER FUNCTION gseg_picksplit(internal, internal) PARALLEL SAFE; +ALTER FUNCTION gseg_union(internal, internal) PARALLEL SAFE; +ALTER FUNCTION gseg_same(seg, seg, internal) PARALLEL SAFE; diff --git a/contrib/seg/seg--1.1--1.2.sql b/contrib/seg/seg--1.1--1.2.sql new file mode 100644 index 0000000..a6e4456 --- /dev/null +++ b/contrib/seg/seg--1.1--1.2.sql @@ -0,0 +1,14 @@ +/* contrib/seg/seg--1.1--1.2.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION seg UPDATE TO '1.2'" to load this file. \quit + +ALTER OPERATOR <= (seg, seg) SET ( + RESTRICT = scalarlesel, + JOIN = scalarlejoinsel +); + +ALTER OPERATOR >= (seg, seg) SET ( + RESTRICT = scalargesel, + JOIN = scalargejoinsel +); diff --git a/contrib/seg/seg--1.1.sql b/contrib/seg/seg--1.1.sql new file mode 100644 index 0000000..d95aabc --- /dev/null +++ b/contrib/seg/seg--1.1.sql @@ -0,0 +1,395 @@ +/* contrib/seg/seg--1.1.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION seg" to load this file. \quit + +-- Create the user-defined type for 1-D floating point intervals (seg) + +CREATE FUNCTION seg_in(cstring) +RETURNS seg +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +CREATE FUNCTION seg_out(seg) +RETURNS cstring +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +CREATE TYPE seg ( + INTERNALLENGTH = 12, + INPUT = seg_in, + OUTPUT = seg_out +); + +COMMENT ON TYPE seg IS +'floating point interval ''FLOAT .. FLOAT'', ''.. FLOAT'', ''FLOAT ..'' or ''FLOAT'''; + +-- +-- External C-functions for R-tree methods +-- + +-- Left/Right methods + +CREATE FUNCTION seg_over_left(seg, seg) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +COMMENT ON FUNCTION seg_over_left(seg, seg) IS +'overlaps or is left of'; + +CREATE FUNCTION seg_over_right(seg, seg) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +COMMENT ON FUNCTION seg_over_right(seg, seg) IS +'overlaps or is right of'; + +CREATE FUNCTION seg_left(seg, seg) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +COMMENT ON FUNCTION seg_left(seg, seg) IS +'is left of'; + +CREATE FUNCTION seg_right(seg, seg) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +COMMENT ON FUNCTION seg_right(seg, seg) IS +'is right of'; + + +-- Scalar comparison methods + +CREATE FUNCTION seg_lt(seg, seg) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +COMMENT ON FUNCTION seg_lt(seg, seg) IS +'less than'; + +CREATE FUNCTION seg_le(seg, seg) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +COMMENT ON FUNCTION seg_le(seg, seg) IS +'less than or equal'; + +CREATE FUNCTION seg_gt(seg, seg) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +COMMENT ON FUNCTION seg_gt(seg, seg) IS +'greater than'; + +CREATE FUNCTION seg_ge(seg, seg) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +COMMENT ON FUNCTION seg_ge(seg, seg) IS +'greater than or equal'; + +CREATE FUNCTION seg_contains(seg, seg) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +COMMENT ON FUNCTION seg_contains(seg, seg) IS +'contains'; + +CREATE FUNCTION seg_contained(seg, seg) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +COMMENT ON FUNCTION seg_contained(seg, seg) IS +'contained in'; + +CREATE FUNCTION seg_overlap(seg, seg) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +COMMENT ON FUNCTION seg_overlap(seg, seg) IS +'overlaps'; + +CREATE FUNCTION seg_same(seg, seg) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +COMMENT ON FUNCTION seg_same(seg, seg) IS +'same as'; + +CREATE FUNCTION seg_different(seg, seg) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +COMMENT ON FUNCTION seg_different(seg, seg) IS +'different'; + +-- support routines for indexing + +CREATE FUNCTION seg_cmp(seg, seg) +RETURNS int4 +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +COMMENT ON FUNCTION seg_cmp(seg, seg) IS 'btree comparison function'; + +CREATE FUNCTION seg_union(seg, seg) +RETURNS seg +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +CREATE FUNCTION seg_inter(seg, seg) +RETURNS seg +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +CREATE FUNCTION seg_size(seg) +RETURNS float4 +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +-- miscellaneous + +CREATE FUNCTION seg_center(seg) +RETURNS float4 +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +CREATE FUNCTION seg_upper(seg) +RETURNS float4 +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +CREATE FUNCTION seg_lower(seg) +RETURNS float4 +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + + +-- +-- OPERATORS +-- + +CREATE OPERATOR < ( + LEFTARG = seg, + RIGHTARG = seg, + PROCEDURE = seg_lt, + COMMUTATOR = '>', + NEGATOR = '>=', + RESTRICT = scalarltsel, + JOIN = scalarltjoinsel +); + +CREATE OPERATOR <= ( + LEFTARG = seg, + RIGHTARG = seg, + PROCEDURE = seg_le, + COMMUTATOR = '>=', + NEGATOR = '>', + RESTRICT = scalarltsel, + JOIN = scalarltjoinsel +); + +CREATE OPERATOR > ( + LEFTARG = seg, + RIGHTARG = seg, + PROCEDURE = seg_gt, + COMMUTATOR = '<', + NEGATOR = '<=', + RESTRICT = scalargtsel, + JOIN = scalargtjoinsel +); + +CREATE OPERATOR >= ( + LEFTARG = seg, + RIGHTARG = seg, + PROCEDURE = seg_ge, + COMMUTATOR = '<=', + NEGATOR = '<', + RESTRICT = scalargtsel, + JOIN = scalargtjoinsel +); + +CREATE OPERATOR << ( + LEFTARG = seg, + RIGHTARG = seg, + PROCEDURE = seg_left, + COMMUTATOR = '>>', + RESTRICT = positionsel, + JOIN = positionjoinsel +); + +CREATE OPERATOR &< ( + LEFTARG = seg, + RIGHTARG = seg, + PROCEDURE = seg_over_left, + RESTRICT = positionsel, + JOIN = positionjoinsel +); + +CREATE OPERATOR && ( + LEFTARG = seg, + RIGHTARG = seg, + PROCEDURE = seg_overlap, + COMMUTATOR = '&&', + RESTRICT = areasel, + JOIN = areajoinsel +); + +CREATE OPERATOR &> ( + LEFTARG = seg, + RIGHTARG = seg, + PROCEDURE = seg_over_right, + RESTRICT = positionsel, + JOIN = positionjoinsel +); + +CREATE OPERATOR >> ( + LEFTARG = seg, + RIGHTARG = seg, + PROCEDURE = seg_right, + COMMUTATOR = '<<', + RESTRICT = positionsel, + JOIN = positionjoinsel +); + +CREATE OPERATOR = ( + LEFTARG = seg, + RIGHTARG = seg, + PROCEDURE = seg_same, + COMMUTATOR = '=', + NEGATOR = '<>', + RESTRICT = eqsel, + JOIN = eqjoinsel, + MERGES +); + +CREATE OPERATOR <> ( + LEFTARG = seg, + RIGHTARG = seg, + PROCEDURE = seg_different, + COMMUTATOR = '<>', + NEGATOR = '=', + RESTRICT = neqsel, + JOIN = neqjoinsel +); + +CREATE OPERATOR @> ( + LEFTARG = seg, + RIGHTARG = seg, + PROCEDURE = seg_contains, + COMMUTATOR = '<@', + RESTRICT = contsel, + JOIN = contjoinsel +); + +CREATE OPERATOR <@ ( + LEFTARG = seg, + RIGHTARG = seg, + PROCEDURE = seg_contained, + COMMUTATOR = '@>', + RESTRICT = contsel, + JOIN = contjoinsel +); + +-- obsolete: +CREATE OPERATOR @ ( + LEFTARG = seg, + RIGHTARG = seg, + PROCEDURE = seg_contains, + COMMUTATOR = '~', + RESTRICT = contsel, + JOIN = contjoinsel +); + +CREATE OPERATOR ~ ( + LEFTARG = seg, + RIGHTARG = seg, + PROCEDURE = seg_contained, + COMMUTATOR = '@', + RESTRICT = contsel, + JOIN = contjoinsel +); + + +-- define the GiST support methods +CREATE FUNCTION gseg_consistent(internal,seg,smallint,oid,internal) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE; + +CREATE FUNCTION gseg_compress(internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE; + +CREATE FUNCTION gseg_decompress(internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE; + +CREATE FUNCTION gseg_penalty(internal,internal,internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE; + +CREATE FUNCTION gseg_picksplit(internal, internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE; + +CREATE FUNCTION gseg_union(internal, internal) +RETURNS seg +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE; + +CREATE FUNCTION gseg_same(seg, seg, internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE; + + +-- Create the operator classes for indexing + +CREATE OPERATOR CLASS seg_ops + DEFAULT FOR TYPE seg USING btree AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 seg_cmp(seg, seg); + +CREATE OPERATOR CLASS gist_seg_ops +DEFAULT FOR TYPE seg USING gist +AS + OPERATOR 1 << , + OPERATOR 2 &< , + OPERATOR 3 && , + OPERATOR 4 &> , + OPERATOR 5 >> , + OPERATOR 6 = , + OPERATOR 7 @> , + OPERATOR 8 <@ , + OPERATOR 13 @ , + OPERATOR 14 ~ , + FUNCTION 1 gseg_consistent (internal, seg, smallint, oid, internal), + FUNCTION 2 gseg_union (internal, internal), + FUNCTION 3 gseg_compress (internal), + FUNCTION 4 gseg_decompress (internal), + FUNCTION 5 gseg_penalty (internal, internal, internal), + FUNCTION 6 gseg_picksplit (internal, internal), + FUNCTION 7 gseg_same (seg, seg, internal); diff --git a/contrib/seg/seg--1.2--1.3.sql b/contrib/seg/seg--1.2--1.3.sql new file mode 100644 index 0000000..578e989 --- /dev/null +++ b/contrib/seg/seg--1.2--1.3.sql @@ -0,0 +1,58 @@ +/* contrib/seg/seg--1.2--1.3.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION seg UPDATE TO '1.3'" to load this file. \quit + +-- +-- Get rid of unnecessary compress and decompress support functions. +-- +-- To be allowed to drop the opclass entry for a support function, +-- we must change the entry's dependency type from 'internal' to 'auto', +-- as though it were a loose member of the opfamily rather than being +-- bound into a particular opclass. There's no SQL command for that, +-- so fake it with a manual update on pg_depend. +-- +DO LANGUAGE plpgsql +$$ +DECLARE + my_schema pg_catalog.text := pg_catalog.quote_ident(pg_catalog.current_schema()); + old_path pg_catalog.text := pg_catalog.current_setting('search_path'); +BEGIN +-- for safety, transiently set search_path to just pg_catalog+pg_temp +PERFORM pg_catalog.set_config('search_path', 'pg_catalog, pg_temp', true); + +UPDATE pg_catalog.pg_depend +SET deptype = 'a' +WHERE classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass + AND objid = + (SELECT objid + FROM pg_catalog.pg_depend + WHERE classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass + AND refclassid = 'pg_catalog.pg_proc'::pg_catalog.regclass + AND (refobjid = (my_schema || '.gseg_compress(internal)')::pg_catalog.regprocedure)) + AND refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass + AND deptype = 'i'; + +UPDATE pg_catalog.pg_depend +SET deptype = 'a' +WHERE classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass + AND objid = + (SELECT objid + FROM pg_catalog.pg_depend + WHERE classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass + AND refclassid = 'pg_catalog.pg_proc'::pg_catalog.regclass + AND (refobjid = (my_schema || '.gseg_decompress(internal)')::pg_catalog.regprocedure)) + AND refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass + AND deptype = 'i'; + +PERFORM pg_catalog.set_config('search_path', old_path, true); +END +$$; + +ALTER OPERATOR FAMILY gist_seg_ops USING gist drop function 3 (seg); +ALTER EXTENSION seg DROP function gseg_compress(pg_catalog.internal); +DROP function gseg_compress(pg_catalog.internal); + +ALTER OPERATOR FAMILY gist_seg_ops USING gist drop function 4 (seg); +ALTER EXTENSION seg DROP function gseg_decompress(pg_catalog.internal); +DROP function gseg_decompress(pg_catalog.internal); diff --git a/contrib/seg/seg--1.3--1.4.sql b/contrib/seg/seg--1.3--1.4.sql new file mode 100644 index 0000000..13babdd --- /dev/null +++ b/contrib/seg/seg--1.3--1.4.sql @@ -0,0 +1,8 @@ +/* contrib/seg/seg--1.3--1.4.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION seg UPDATE TO '1.4'" to load this file. \quit + +-- Remove @ and ~ +DROP OPERATOR @ (seg, seg); +DROP OPERATOR ~ (seg, seg); diff --git a/contrib/seg/seg-validate.pl b/contrib/seg/seg-validate.pl new file mode 100755 index 0000000..3d27492 --- /dev/null +++ b/contrib/seg/seg-validate.pl @@ -0,0 +1,56 @@ +#!/usr/bin/perl + +# Copyright (c) 2021-2022, PostgreSQL Global Development Group + +use strict; +use warnings; + +my $integer = '[+-]?[0-9]+'; +my $real = '[+-]?[0-9]+\.[0-9]+'; + +my $RANGE = '(\.\.)(\.)?'; +my $PLUMIN = q(\'\+\-\'); +my $FLOAT = "(($integer)|($real))([eE]($integer))?"; +my $EXTENSION = '<|>|~'; + +my $boundary = "($EXTENSION)?$FLOAT"; +my $deviation = $FLOAT; + +my $rule_1 = $boundary . $PLUMIN . $deviation; +my $rule_2 = $boundary . $RANGE . $boundary; +my $rule_3 = $boundary . $RANGE; +my $rule_4 = $RANGE . $boundary; +my $rule_5 = $boundary; + + +print "$rule_5\n"; +while (<>) +{ + + # s/ +//g; + if (/^($rule_1)$/) + { + print; + } + elsif (/^($rule_2)$/) + { + print; + } + elsif (/^($rule_3)$/) + { + print; + } + elsif (/^($rule_4)$/) + { + print; + } + elsif (/^($rule_5)$/) + { + print; + } + else + { + print STDERR "error in $_\n"; + } + +} diff --git a/contrib/seg/seg.c b/contrib/seg/seg.c new file mode 100644 index 0000000..91b8a79 --- /dev/null +++ b/contrib/seg/seg.c @@ -0,0 +1,1094 @@ +/* + * contrib/seg/seg.c + * + ****************************************************************************** + This file contains routines that can be bound to a Postgres backend and + called by the backend in the process of processing queries. The calling + format for these routines is dictated by Postgres architecture. +******************************************************************************/ + +#include "postgres.h" + +#include <float.h> + +#include "access/gist.h" +#include "access/stratnum.h" +#include "fmgr.h" + +#include "segdata.h" + + +#define DatumGetSegP(X) ((SEG *) DatumGetPointer(X)) +#define PG_GETARG_SEG_P(n) DatumGetSegP(PG_GETARG_DATUM(n)) + + +/* +#define GIST_DEBUG +#define GIST_QUERY_DEBUG +*/ + +PG_MODULE_MAGIC; + +/* + * Auxiliary data structure for picksplit method. + */ +typedef struct +{ + float center; + OffsetNumber index; + SEG *data; +} gseg_picksplit_item; + +/* +** Input/Output routines +*/ +PG_FUNCTION_INFO_V1(seg_in); +PG_FUNCTION_INFO_V1(seg_out); +PG_FUNCTION_INFO_V1(seg_size); +PG_FUNCTION_INFO_V1(seg_lower); +PG_FUNCTION_INFO_V1(seg_upper); +PG_FUNCTION_INFO_V1(seg_center); + +/* +** GiST support methods +*/ +PG_FUNCTION_INFO_V1(gseg_consistent); +PG_FUNCTION_INFO_V1(gseg_compress); +PG_FUNCTION_INFO_V1(gseg_decompress); +PG_FUNCTION_INFO_V1(gseg_picksplit); +PG_FUNCTION_INFO_V1(gseg_penalty); +PG_FUNCTION_INFO_V1(gseg_union); +PG_FUNCTION_INFO_V1(gseg_same); +static Datum gseg_leaf_consistent(Datum key, Datum query, StrategyNumber strategy); +static Datum gseg_internal_consistent(Datum key, Datum query, StrategyNumber strategy); +static Datum gseg_binary_union(Datum r1, Datum r2, int *sizep); + + +/* +** R-tree support functions +*/ +PG_FUNCTION_INFO_V1(seg_same); +PG_FUNCTION_INFO_V1(seg_contains); +PG_FUNCTION_INFO_V1(seg_contained); +PG_FUNCTION_INFO_V1(seg_overlap); +PG_FUNCTION_INFO_V1(seg_left); +PG_FUNCTION_INFO_V1(seg_over_left); +PG_FUNCTION_INFO_V1(seg_right); +PG_FUNCTION_INFO_V1(seg_over_right); +PG_FUNCTION_INFO_V1(seg_union); +PG_FUNCTION_INFO_V1(seg_inter); +static void rt_seg_size(SEG *a, float *size); + +/* +** Various operators +*/ +PG_FUNCTION_INFO_V1(seg_cmp); +PG_FUNCTION_INFO_V1(seg_lt); +PG_FUNCTION_INFO_V1(seg_le); +PG_FUNCTION_INFO_V1(seg_gt); +PG_FUNCTION_INFO_V1(seg_ge); +PG_FUNCTION_INFO_V1(seg_different); + +/* +** Auxiliary functions +*/ +static int restore(char *s, float val, int n); + + +/***************************************************************************** + * Input/Output functions + *****************************************************************************/ + +Datum +seg_in(PG_FUNCTION_ARGS) +{ + char *str = PG_GETARG_CSTRING(0); + SEG *result = palloc(sizeof(SEG)); + + seg_scanner_init(str); + + if (seg_yyparse(result) != 0) + seg_yyerror(result, "bogus input"); + + seg_scanner_finish(); + + PG_RETURN_POINTER(result); +} + +Datum +seg_out(PG_FUNCTION_ARGS) +{ + SEG *seg = PG_GETARG_SEG_P(0); + char *result; + char *p; + + p = result = (char *) palloc(40); + + if (seg->l_ext == '>' || seg->l_ext == '<' || seg->l_ext == '~') + p += sprintf(p, "%c", seg->l_ext); + + if (seg->lower == seg->upper && seg->l_ext == seg->u_ext) + { + /* + * indicates that this interval was built by seg_in off a single point + */ + p += restore(p, seg->lower, seg->l_sigd); + } + else + { + if (seg->l_ext != '-') + { + /* print the lower boundary if exists */ + p += restore(p, seg->lower, seg->l_sigd); + p += sprintf(p, " "); + } + p += sprintf(p, ".."); + if (seg->u_ext != '-') + { + /* print the upper boundary if exists */ + p += sprintf(p, " "); + if (seg->u_ext == '>' || seg->u_ext == '<' || seg->l_ext == '~') + p += sprintf(p, "%c", seg->u_ext); + p += restore(p, seg->upper, seg->u_sigd); + } + } + + PG_RETURN_CSTRING(result); +} + +Datum +seg_center(PG_FUNCTION_ARGS) +{ + SEG *seg = PG_GETARG_SEG_P(0); + + PG_RETURN_FLOAT4(((float) seg->lower + (float) seg->upper) / 2.0); +} + +Datum +seg_lower(PG_FUNCTION_ARGS) +{ + SEG *seg = PG_GETARG_SEG_P(0); + + PG_RETURN_FLOAT4(seg->lower); +} + +Datum +seg_upper(PG_FUNCTION_ARGS) +{ + SEG *seg = PG_GETARG_SEG_P(0); + + PG_RETURN_FLOAT4(seg->upper); +} + + +/***************************************************************************** + * GiST functions + *****************************************************************************/ + +/* +** The GiST Consistent method for segments +** Should return false if for all data items x below entry, +** the predicate x op query == false, where op is the oper +** corresponding to strategy in the pg_amop table. +*/ +Datum +gseg_consistent(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + Datum query = PG_GETARG_DATUM(1); + StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); + + /* Oid subtype = PG_GETARG_OID(3); */ + bool *recheck = (bool *) PG_GETARG_POINTER(4); + + /* All cases served by this function are exact */ + *recheck = false; + + /* + * if entry is not leaf, use gseg_internal_consistent, else use + * gseg_leaf_consistent + */ + if (GIST_LEAF(entry)) + return gseg_leaf_consistent(entry->key, query, strategy); + else + return gseg_internal_consistent(entry->key, query, strategy); +} + +/* +** The GiST Union method for segments +** returns the minimal bounding seg that encloses all the entries in entryvec +*/ +Datum +gseg_union(PG_FUNCTION_ARGS) +{ + GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); + int *sizep = (int *) PG_GETARG_POINTER(1); + int numranges, + i; + Datum out = 0; + Datum tmp; + +#ifdef GIST_DEBUG + fprintf(stderr, "union\n"); +#endif + + numranges = entryvec->n; + tmp = entryvec->vector[0].key; + *sizep = sizeof(SEG); + + for (i = 1; i < numranges; i++) + { + out = gseg_binary_union(tmp, entryvec->vector[i].key, sizep); + tmp = out; + } + + PG_RETURN_DATUM(out); +} + +/* +** GiST Compress and Decompress methods for segments +** do not do anything. +*/ +Datum +gseg_compress(PG_FUNCTION_ARGS) +{ + PG_RETURN_POINTER(PG_GETARG_POINTER(0)); +} + +Datum +gseg_decompress(PG_FUNCTION_ARGS) +{ + PG_RETURN_POINTER(PG_GETARG_POINTER(0)); +} + +/* +** The GiST Penalty method for segments +** As in the R-tree paper, we use change in area as our penalty metric +*/ +Datum +gseg_penalty(PG_FUNCTION_ARGS) +{ + GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); + GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1); + float *result = (float *) PG_GETARG_POINTER(2); + SEG *ud; + float tmp1, + tmp2; + + ud = DatumGetSegP(DirectFunctionCall2(seg_union, + origentry->key, + newentry->key)); + rt_seg_size(ud, &tmp1); + rt_seg_size(DatumGetSegP(origentry->key), &tmp2); + *result = tmp1 - tmp2; + +#ifdef GIST_DEBUG + fprintf(stderr, "penalty\n"); + fprintf(stderr, "\t%g\n", *result); +#endif + + PG_RETURN_POINTER(result); +} + +/* + * Compare function for gseg_picksplit_item: sort by center. + */ +static int +gseg_picksplit_item_cmp(const void *a, const void *b) +{ + const gseg_picksplit_item *i1 = (const gseg_picksplit_item *) a; + const gseg_picksplit_item *i2 = (const gseg_picksplit_item *) b; + + if (i1->center < i2->center) + return -1; + else if (i1->center == i2->center) + return 0; + else + return 1; +} + +/* + * The GiST PickSplit method for segments + * + * We used to use Guttman's split algorithm here, but since the data is 1-D + * it's easier and more robust to just sort the segments by center-point and + * split at the middle. + */ +Datum +gseg_picksplit(PG_FUNCTION_ARGS) +{ + GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); + GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1); + int i; + SEG *seg, + *seg_l, + *seg_r; + gseg_picksplit_item *sort_items; + OffsetNumber *left, + *right; + OffsetNumber maxoff; + OffsetNumber firstright; + +#ifdef GIST_DEBUG + fprintf(stderr, "picksplit\n"); +#endif + + /* Valid items in entryvec->vector[] are indexed 1..maxoff */ + maxoff = entryvec->n - 1; + + /* + * Prepare the auxiliary array and sort it. + */ + sort_items = (gseg_picksplit_item *) + palloc(maxoff * sizeof(gseg_picksplit_item)); + for (i = 1; i <= maxoff; i++) + { + seg = DatumGetSegP(entryvec->vector[i].key); + /* center calculation is done this way to avoid possible overflow */ + sort_items[i - 1].center = seg->lower * 0.5f + seg->upper * 0.5f; + sort_items[i - 1].index = i; + sort_items[i - 1].data = seg; + } + qsort(sort_items, maxoff, sizeof(gseg_picksplit_item), + gseg_picksplit_item_cmp); + + /* sort items below "firstright" will go into the left side */ + firstright = maxoff / 2; + + v->spl_left = (OffsetNumber *) palloc(maxoff * sizeof(OffsetNumber)); + v->spl_right = (OffsetNumber *) palloc(maxoff * sizeof(OffsetNumber)); + left = v->spl_left; + v->spl_nleft = 0; + right = v->spl_right; + v->spl_nright = 0; + + /* + * Emit segments to the left output page, and compute its bounding box. + */ + seg_l = (SEG *) palloc(sizeof(SEG)); + memcpy(seg_l, sort_items[0].data, sizeof(SEG)); + *left++ = sort_items[0].index; + v->spl_nleft++; + for (i = 1; i < firstright; i++) + { + Datum sortitem = PointerGetDatum(sort_items[i].data); + + seg_l = DatumGetSegP(DirectFunctionCall2(seg_union, + PointerGetDatum(seg_l), + sortitem)); + *left++ = sort_items[i].index; + v->spl_nleft++; + } + + /* + * Likewise for the right page. + */ + seg_r = (SEG *) palloc(sizeof(SEG)); + memcpy(seg_r, sort_items[firstright].data, sizeof(SEG)); + *right++ = sort_items[firstright].index; + v->spl_nright++; + for (i = firstright + 1; i < maxoff; i++) + { + Datum sortitem = PointerGetDatum(sort_items[i].data); + + seg_r = DatumGetSegP(DirectFunctionCall2(seg_union, + PointerGetDatum(seg_r), + sortitem)); + *right++ = sort_items[i].index; + v->spl_nright++; + } + + v->spl_ldatum = PointerGetDatum(seg_l); + v->spl_rdatum = PointerGetDatum(seg_r); + + PG_RETURN_POINTER(v); +} + +/* +** Equality methods +*/ +Datum +gseg_same(PG_FUNCTION_ARGS) +{ + bool *result = (bool *) PG_GETARG_POINTER(2); + + if (DirectFunctionCall2(seg_same, PG_GETARG_DATUM(0), PG_GETARG_DATUM(1))) + *result = true; + else + *result = false; + +#ifdef GIST_DEBUG + fprintf(stderr, "same: %s\n", (*result ? "TRUE" : "FALSE")); +#endif + + PG_RETURN_POINTER(result); +} + +/* +** SUPPORT ROUTINES +*/ +static Datum +gseg_leaf_consistent(Datum key, Datum query, StrategyNumber strategy) +{ + Datum retval; + +#ifdef GIST_QUERY_DEBUG + fprintf(stderr, "leaf_consistent, %d\n", strategy); +#endif + + switch (strategy) + { + case RTLeftStrategyNumber: + retval = DirectFunctionCall2(seg_left, key, query); + break; + case RTOverLeftStrategyNumber: + retval = DirectFunctionCall2(seg_over_left, key, query); + break; + case RTOverlapStrategyNumber: + retval = DirectFunctionCall2(seg_overlap, key, query); + break; + case RTOverRightStrategyNumber: + retval = DirectFunctionCall2(seg_over_right, key, query); + break; + case RTRightStrategyNumber: + retval = DirectFunctionCall2(seg_right, key, query); + break; + case RTSameStrategyNumber: + retval = DirectFunctionCall2(seg_same, key, query); + break; + case RTContainsStrategyNumber: + case RTOldContainsStrategyNumber: + retval = DirectFunctionCall2(seg_contains, key, query); + break; + case RTContainedByStrategyNumber: + case RTOldContainedByStrategyNumber: + retval = DirectFunctionCall2(seg_contained, key, query); + break; + default: + retval = false; + } + + PG_RETURN_DATUM(retval); +} + +static Datum +gseg_internal_consistent(Datum key, Datum query, StrategyNumber strategy) +{ + bool retval; + +#ifdef GIST_QUERY_DEBUG + fprintf(stderr, "internal_consistent, %d\n", strategy); +#endif + + switch (strategy) + { + case RTLeftStrategyNumber: + retval = + !DatumGetBool(DirectFunctionCall2(seg_over_right, key, query)); + break; + case RTOverLeftStrategyNumber: + retval = + !DatumGetBool(DirectFunctionCall2(seg_right, key, query)); + break; + case RTOverlapStrategyNumber: + retval = + DatumGetBool(DirectFunctionCall2(seg_overlap, key, query)); + break; + case RTOverRightStrategyNumber: + retval = + !DatumGetBool(DirectFunctionCall2(seg_left, key, query)); + break; + case RTRightStrategyNumber: + retval = + !DatumGetBool(DirectFunctionCall2(seg_over_left, key, query)); + break; + case RTSameStrategyNumber: + case RTContainsStrategyNumber: + case RTOldContainsStrategyNumber: + retval = + DatumGetBool(DirectFunctionCall2(seg_contains, key, query)); + break; + case RTContainedByStrategyNumber: + case RTOldContainedByStrategyNumber: + retval = + DatumGetBool(DirectFunctionCall2(seg_overlap, key, query)); + break; + default: + retval = false; + } + + PG_RETURN_BOOL(retval); +} + +static Datum +gseg_binary_union(Datum r1, Datum r2, int *sizep) +{ + Datum retval; + + retval = DirectFunctionCall2(seg_union, r1, r2); + *sizep = sizeof(SEG); + + return retval; +} + + +Datum +seg_contains(PG_FUNCTION_ARGS) +{ + SEG *a = PG_GETARG_SEG_P(0); + SEG *b = PG_GETARG_SEG_P(1); + + PG_RETURN_BOOL((a->lower <= b->lower) && (a->upper >= b->upper)); +} + +Datum +seg_contained(PG_FUNCTION_ARGS) +{ + Datum a = PG_GETARG_DATUM(0); + Datum b = PG_GETARG_DATUM(1); + + PG_RETURN_DATUM(DirectFunctionCall2(seg_contains, b, a)); +} + +/***************************************************************************** + * Operator class for R-tree indexing + *****************************************************************************/ + +Datum +seg_same(PG_FUNCTION_ARGS) +{ + int cmp = DatumGetInt32(DirectFunctionCall2(seg_cmp, + PG_GETARG_DATUM(0), + PG_GETARG_DATUM(1))); + + PG_RETURN_BOOL(cmp == 0); +} + +/* seg_overlap -- does a overlap b? + */ +Datum +seg_overlap(PG_FUNCTION_ARGS) +{ + SEG *a = PG_GETARG_SEG_P(0); + SEG *b = PG_GETARG_SEG_P(1); + + PG_RETURN_BOOL(((a->upper >= b->upper) && (a->lower <= b->upper)) || + ((b->upper >= a->upper) && (b->lower <= a->upper))); +} + +/* seg_over_left -- is the right edge of (a) located at or left of the right edge of (b)? + */ +Datum +seg_over_left(PG_FUNCTION_ARGS) +{ + SEG *a = PG_GETARG_SEG_P(0); + SEG *b = PG_GETARG_SEG_P(1); + + PG_RETURN_BOOL(a->upper <= b->upper); +} + +/* seg_left -- is (a) entirely on the left of (b)? + */ +Datum +seg_left(PG_FUNCTION_ARGS) +{ + SEG *a = PG_GETARG_SEG_P(0); + SEG *b = PG_GETARG_SEG_P(1); + + PG_RETURN_BOOL(a->upper < b->lower); +} + +/* seg_right -- is (a) entirely on the right of (b)? + */ +Datum +seg_right(PG_FUNCTION_ARGS) +{ + SEG *a = PG_GETARG_SEG_P(0); + SEG *b = PG_GETARG_SEG_P(1); + + PG_RETURN_BOOL(a->lower > b->upper); +} + +/* seg_over_right -- is the left edge of (a) located at or right of the left edge of (b)? + */ +Datum +seg_over_right(PG_FUNCTION_ARGS) +{ + SEG *a = PG_GETARG_SEG_P(0); + SEG *b = PG_GETARG_SEG_P(1); + + PG_RETURN_BOOL(a->lower >= b->lower); +} + +Datum +seg_union(PG_FUNCTION_ARGS) +{ + SEG *a = PG_GETARG_SEG_P(0); + SEG *b = PG_GETARG_SEG_P(1); + SEG *n; + + n = (SEG *) palloc(sizeof(*n)); + + /* take max of upper endpoints */ + if (a->upper > b->upper) + { + n->upper = a->upper; + n->u_sigd = a->u_sigd; + n->u_ext = a->u_ext; + } + else + { + n->upper = b->upper; + n->u_sigd = b->u_sigd; + n->u_ext = b->u_ext; + } + + /* take min of lower endpoints */ + if (a->lower < b->lower) + { + n->lower = a->lower; + n->l_sigd = a->l_sigd; + n->l_ext = a->l_ext; + } + else + { + n->lower = b->lower; + n->l_sigd = b->l_sigd; + n->l_ext = b->l_ext; + } + + PG_RETURN_POINTER(n); +} + +Datum +seg_inter(PG_FUNCTION_ARGS) +{ + SEG *a = PG_GETARG_SEG_P(0); + SEG *b = PG_GETARG_SEG_P(1); + SEG *n; + + n = (SEG *) palloc(sizeof(*n)); + + /* take min of upper endpoints */ + if (a->upper < b->upper) + { + n->upper = a->upper; + n->u_sigd = a->u_sigd; + n->u_ext = a->u_ext; + } + else + { + n->upper = b->upper; + n->u_sigd = b->u_sigd; + n->u_ext = b->u_ext; + } + + /* take max of lower endpoints */ + if (a->lower > b->lower) + { + n->lower = a->lower; + n->l_sigd = a->l_sigd; + n->l_ext = a->l_ext; + } + else + { + n->lower = b->lower; + n->l_sigd = b->l_sigd; + n->l_ext = b->l_ext; + } + + PG_RETURN_POINTER(n); +} + +static void +rt_seg_size(SEG *a, float *size) +{ + if (a == (SEG *) NULL || a->upper <= a->lower) + *size = 0.0; + else + *size = (float) Abs(a->upper - a->lower); +} + +Datum +seg_size(PG_FUNCTION_ARGS) +{ + SEG *seg = PG_GETARG_SEG_P(0); + + PG_RETURN_FLOAT4((float) Abs(seg->upper - seg->lower)); +} + + +/***************************************************************************** + * Miscellaneous operators + *****************************************************************************/ +Datum +seg_cmp(PG_FUNCTION_ARGS) +{ + SEG *a = PG_GETARG_SEG_P(0); + SEG *b = PG_GETARG_SEG_P(1); + + /* + * First compare on lower boundary position + */ + if (a->lower < b->lower) + PG_RETURN_INT32(-1); + if (a->lower > b->lower) + PG_RETURN_INT32(1); + + /* + * a->lower == b->lower, so consider type of boundary. + * + * A '-' lower bound is < any other kind (this could only be relevant if + * -HUGE_VAL is used as a regular data value). A '<' lower bound is < any + * other kind except '-'. A '>' lower bound is > any other kind. + */ + if (a->l_ext != b->l_ext) + { + if (a->l_ext == '-') + PG_RETURN_INT32(-1); + if (b->l_ext == '-') + PG_RETURN_INT32(1); + if (a->l_ext == '<') + PG_RETURN_INT32(-1); + if (b->l_ext == '<') + PG_RETURN_INT32(1); + if (a->l_ext == '>') + PG_RETURN_INT32(1); + if (b->l_ext == '>') + PG_RETURN_INT32(-1); + } + + /* + * For other boundary types, consider # of significant digits first. + */ + if (a->l_sigd < b->l_sigd) /* (a) is blurred and is likely to include (b) */ + PG_RETURN_INT32(-1); + if (a->l_sigd > b->l_sigd) /* (a) is less blurred and is likely to be + * included in (b) */ + PG_RETURN_INT32(1); + + /* + * For same # of digits, an approximate boundary is more blurred than + * exact. + */ + if (a->l_ext != b->l_ext) + { + if (a->l_ext == '~') /* (a) is approximate, while (b) is exact */ + PG_RETURN_INT32(-1); + if (b->l_ext == '~') + PG_RETURN_INT32(1); + /* can't get here unless data is corrupt */ + elog(ERROR, "bogus lower boundary types %d %d", + (int) a->l_ext, (int) b->l_ext); + } + + /* at this point, the lower boundaries are identical */ + + /* + * First compare on upper boundary position + */ + if (a->upper < b->upper) + PG_RETURN_INT32(-1); + if (a->upper > b->upper) + PG_RETURN_INT32(1); + + /* + * a->upper == b->upper, so consider type of boundary. + * + * A '-' upper bound is > any other kind (this could only be relevant if + * HUGE_VAL is used as a regular data value). A '<' upper bound is < any + * other kind. A '>' upper bound is > any other kind except '-'. + */ + if (a->u_ext != b->u_ext) + { + if (a->u_ext == '-') + PG_RETURN_INT32(1); + if (b->u_ext == '-') + PG_RETURN_INT32(-1); + if (a->u_ext == '<') + PG_RETURN_INT32(-1); + if (b->u_ext == '<') + PG_RETURN_INT32(1); + if (a->u_ext == '>') + PG_RETURN_INT32(1); + if (b->u_ext == '>') + PG_RETURN_INT32(-1); + } + + /* + * For other boundary types, consider # of significant digits first. Note + * result here is converse of the lower-boundary case. + */ + if (a->u_sigd < b->u_sigd) /* (a) is blurred and is likely to include (b) */ + PG_RETURN_INT32(1); + if (a->u_sigd > b->u_sigd) /* (a) is less blurred and is likely to be + * included in (b) */ + PG_RETURN_INT32(-1); + + /* + * For same # of digits, an approximate boundary is more blurred than + * exact. Again, result is converse of lower-boundary case. + */ + if (a->u_ext != b->u_ext) + { + if (a->u_ext == '~') /* (a) is approximate, while (b) is exact */ + PG_RETURN_INT32(1); + if (b->u_ext == '~') + PG_RETURN_INT32(-1); + /* can't get here unless data is corrupt */ + elog(ERROR, "bogus upper boundary types %d %d", + (int) a->u_ext, (int) b->u_ext); + } + + PG_RETURN_INT32(0); +} + +Datum +seg_lt(PG_FUNCTION_ARGS) +{ + int cmp = DatumGetInt32(DirectFunctionCall2(seg_cmp, + PG_GETARG_DATUM(0), + PG_GETARG_DATUM(1))); + + PG_RETURN_BOOL(cmp < 0); +} + +Datum +seg_le(PG_FUNCTION_ARGS) +{ + int cmp = DatumGetInt32(DirectFunctionCall2(seg_cmp, + PG_GETARG_DATUM(0), + PG_GETARG_DATUM(1))); + + PG_RETURN_BOOL(cmp <= 0); +} + +Datum +seg_gt(PG_FUNCTION_ARGS) +{ + int cmp = DatumGetInt32(DirectFunctionCall2(seg_cmp, + PG_GETARG_DATUM(0), + PG_GETARG_DATUM(1))); + + PG_RETURN_BOOL(cmp > 0); +} + +Datum +seg_ge(PG_FUNCTION_ARGS) +{ + int cmp = DatumGetInt32(DirectFunctionCall2(seg_cmp, + PG_GETARG_DATUM(0), + PG_GETARG_DATUM(1))); + + PG_RETURN_BOOL(cmp >= 0); +} + + +Datum +seg_different(PG_FUNCTION_ARGS) +{ + int cmp = DatumGetInt32(DirectFunctionCall2(seg_cmp, + PG_GETARG_DATUM(0), + PG_GETARG_DATUM(1))); + + PG_RETURN_BOOL(cmp != 0); +} + + + +/***************************************************************************** + * Auxiliary functions + *****************************************************************************/ + +/* + * The purpose of this routine is to print the given floating point + * value with exactly n significant digits. Its behaviour + * is similar to %.ng except it prints 8.00 where %.ng would + * print 8. Returns the length of the string written at "result". + * + * Caller must provide a sufficiently large result buffer; 16 bytes + * should be enough for all known float implementations. + */ +static int +restore(char *result, float val, int n) +{ + char buf[25] = { + '0', '0', '0', '0', '0', + '0', '0', '0', '0', '0', + '0', '0', '0', '0', '0', + '0', '0', '0', '0', '0', + '0', '0', '0', '0', '\0' + }; + char *p; + int exp; + int i, + dp, + sign; + + /* + * Put a cap on the number of significant digits to avoid garbage in the + * output and ensure we don't overrun the result buffer. (n should not be + * negative, but check to protect ourselves against corrupted data.) + */ + if (n <= 0) + n = FLT_DIG; + else + n = Min(n, FLT_DIG); + + /* remember the sign */ + sign = (val < 0 ? 1 : 0); + + /* print, in %e style to start with */ + sprintf(result, "%.*e", n - 1, val); + + /* find the exponent */ + p = strchr(result, 'e'); + + /* punt if we have 'inf' or similar */ + if (p == NULL) + return strlen(result); + + exp = atoi(p + 1); + if (exp == 0) + { + /* just truncate off the 'e+00' */ + *p = '\0'; + } + else + { + if (Abs(exp) <= 4) + { + /* + * remove the decimal point from the mantissa and write the digits + * to the buf array + */ + for (p = result + sign, i = 10, dp = 0; *p != 'e'; p++, i++) + { + buf[i] = *p; + if (*p == '.') + { + dp = i--; /* skip the decimal point */ + } + } + if (dp == 0) + dp = i--; /* no decimal point was found in the above + * for() loop */ + + if (exp > 0) + { + if (dp - 10 + exp >= n) + { + /* + * the decimal point is behind the last significant digit; + * the digits in between must be converted to the exponent + * and the decimal point placed after the first digit + */ + exp = dp - 10 + exp - n; + buf[10 + n] = '\0'; + + /* insert the decimal point */ + if (n > 1) + { + dp = 11; + for (i = 23; i > dp; i--) + buf[i] = buf[i - 1]; + buf[dp] = '.'; + } + + /* + * adjust the exponent by the number of digits after the + * decimal point + */ + if (n > 1) + sprintf(&buf[11 + n], "e%d", exp + n - 1); + else + sprintf(&buf[11], "e%d", exp + n - 1); + + if (sign) + { + buf[9] = '-'; + strcpy(result, &buf[9]); + } + else + strcpy(result, &buf[10]); + } + else + { /* insert the decimal point */ + dp += exp; + for (i = 23; i > dp; i--) + buf[i] = buf[i - 1]; + buf[11 + n] = '\0'; + buf[dp] = '.'; + if (sign) + { + buf[9] = '-'; + strcpy(result, &buf[9]); + } + else + strcpy(result, &buf[10]); + } + } + else + { /* exp <= 0 */ + dp += exp - 1; + buf[10 + n] = '\0'; + buf[dp] = '.'; + if (sign) + { + buf[dp - 2] = '-'; + strcpy(result, &buf[dp - 2]); + } + else + strcpy(result, &buf[dp - 1]); + } + } + + /* do nothing for Abs(exp) > 4; %e must be OK */ + /* just get rid of zeroes after [eE]- and +zeroes after [Ee]. */ + + /* ... this is not done yet. */ + } + return strlen(result); +} + + +/* +** Miscellany +*/ + +/* find out the number of significant digits in a string representing + * a floating point number + */ +int +significant_digits(const char *s) +{ + const char *p = s; + int n, + c, + zeroes; + + zeroes = 1; + /* skip leading zeroes and sign */ + for (c = *p; (c == '0' || c == '+' || c == '-') && c != 0; c = *(++p)); + + /* skip decimal point and following zeroes */ + for (c = *p; (c == '0' || c == '.') && c != 0; c = *(++p)) + { + if (c != '.') + zeroes++; + } + + /* count significant digits (n) */ + for (c = *p, n = 0; c != 0; c = *(++p)) + { + if (!((c >= '0' && c <= '9') || (c == '.'))) + break; + if (c != '.') + n++; + } + + if (!n) + return zeroes; + + return n; +} diff --git a/contrib/seg/seg.control b/contrib/seg/seg.control new file mode 100644 index 0000000..e2c6a47 --- /dev/null +++ b/contrib/seg/seg.control @@ -0,0 +1,6 @@ +# seg extension +comment = 'data type for representing line segments or floating-point intervals' +default_version = '1.4' +module_pathname = '$libdir/seg' +relocatable = true +trusted = true diff --git a/contrib/seg/segdata.h b/contrib/seg/segdata.h new file mode 100644 index 0000000..9488bf3 --- /dev/null +++ b/contrib/seg/segdata.h @@ -0,0 +1,24 @@ +/* + * contrib/seg/segdata.h + */ +typedef struct SEG +{ + float4 lower; + float4 upper; + char l_sigd; + char u_sigd; + char l_ext; + char u_ext; +} SEG; + +/* in seg.c */ +extern int significant_digits(const char *str); + +/* in segscan.l */ +extern int seg_yylex(void); +extern void seg_yyerror(SEG *result, const char *message) pg_attribute_noreturn(); +extern void seg_scanner_init(const char *str); +extern void seg_scanner_finish(void); + +/* in segparse.y */ +extern int seg_yyparse(SEG *result); diff --git a/contrib/seg/segparse.c b/contrib/seg/segparse.c new file mode 100644 index 0000000..500fb80 --- /dev/null +++ b/contrib/seg/segparse.c @@ -0,0 +1,1492 @@ +/* A Bison parser, made by GNU Bison 3.7.5. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, + especially those whose name start with YY_ or yy_. They are + private implementation details that can be changed or removed. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output, and Bison version. */ +#define YYBISON 30705 + +/* Bison version string. */ +#define YYBISON_VERSION "3.7.5" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + + +/* Substitute the variable and function names. */ +#define yyparse seg_yyparse +#define yylex seg_yylex +#define yyerror seg_yyerror +#define yydebug seg_yydebug +#define yynerrs seg_yynerrs +#define yylval seg_yylval +#define yychar seg_yychar + +/* First part of user prologue. */ +#line 1 "segparse.y" + +/* contrib/seg/segparse.y */ + +#include "postgres.h" + +#include <float.h> +#include <math.h> + +#include "fmgr.h" +#include "utils/builtins.h" + +#include "segdata.h" + +/* + * Bison doesn't allocate anything that needs to live across parser calls, + * so we can easily have it use palloc instead of malloc. This prevents + * memory leaks if we error out during parsing. Note this only works with + * bison >= 2.0. However, in bison 1.875 the default is to use alloca() + * if possible, so there's not really much problem anyhow, at least if + * you're building with gcc. + */ +#define YYMALLOC palloc +#define YYFREE pfree + +static float seg_atof(const char *value); + +static int sig_digits(const char *value); + +static char strbuf[25] = { + '0', '0', '0', '0', '0', + '0', '0', '0', '0', '0', + '0', '0', '0', '0', '0', + '0', '0', '0', '0', '0', + '0', '0', '0', '0', '\0' +}; + + +#line 116 "segparse.c" + +# ifndef YY_CAST +# ifdef __cplusplus +# define YY_CAST(Type, Val) static_cast<Type> (Val) +# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast<Type> (Val) +# else +# define YY_CAST(Type, Val) ((Type) (Val)) +# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) +# endif +# endif +# ifndef YY_NULLPTR +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# else +# define YY_NULLPTR ((void*)0) +# endif +# endif + + +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int seg_yydebug; +#endif + +/* Token kinds. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + YYEMPTY = -2, + YYEOF = 0, /* "end of file" */ + YYerror = 256, /* error */ + YYUNDEF = 257, /* "invalid token" */ + SEGFLOAT = 258, /* SEGFLOAT */ + RANGE = 259, /* RANGE */ + PLUMIN = 260, /* PLUMIN */ + EXTENSION = 261 /* EXTENSION */ + }; + typedef enum yytokentype yytoken_kind_t; +#endif + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +union YYSTYPE +{ +#line 45 "segparse.y" + + struct BND + { + float val; + char ext; + char sigd; + } bnd; + char *text; + +#line 179 "segparse.c" + +}; +typedef union YYSTYPE YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + +extern YYSTYPE seg_yylval; + +int seg_yyparse (SEG *result); + + +/* Symbol kind. */ +enum yysymbol_kind_t +{ + YYSYMBOL_YYEMPTY = -2, + YYSYMBOL_YYEOF = 0, /* "end of file" */ + YYSYMBOL_YYerror = 1, /* error */ + YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ + YYSYMBOL_SEGFLOAT = 3, /* SEGFLOAT */ + YYSYMBOL_RANGE = 4, /* RANGE */ + YYSYMBOL_PLUMIN = 5, /* PLUMIN */ + YYSYMBOL_EXTENSION = 6, /* EXTENSION */ + YYSYMBOL_YYACCEPT = 7, /* $accept */ + YYSYMBOL_range = 8, /* range */ + YYSYMBOL_boundary = 9, /* boundary */ + YYSYMBOL_deviation = 10 /* deviation */ +}; +typedef enum yysymbol_kind_t yysymbol_kind_t; + + + + +#ifdef short +# undef short +#endif + +/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure + <limits.h> and (if available) <stdint.h> are included + so that the code can choose integer types of a good width. */ + +#ifndef __PTRDIFF_MAX__ +# include <limits.h> /* INFRINGES ON USER NAME SPACE */ +# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include <stdint.h> /* INFRINGES ON USER NAME SPACE */ +# define YY_STDINT_H +# endif +#endif + +/* Narrow types that promote to a signed type and that can represent a + signed or unsigned integer of at least N bits. In tables they can + save space and decrease cache pressure. Promoting to a signed type + helps avoid bugs in integer arithmetic. */ + +#ifdef __INT_LEAST8_MAX__ +typedef __INT_LEAST8_TYPE__ yytype_int8; +#elif defined YY_STDINT_H +typedef int_least8_t yytype_int8; +#else +typedef signed char yytype_int8; +#endif + +#ifdef __INT_LEAST16_MAX__ +typedef __INT_LEAST16_TYPE__ yytype_int16; +#elif defined YY_STDINT_H +typedef int_least16_t yytype_int16; +#else +typedef short yytype_int16; +#endif + +/* Work around bug in HP-UX 11.23, which defines these macros + incorrectly for preprocessor constants. This workaround can likely + be removed in 2023, as HPE has promised support for HP-UX 11.23 + (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of + <https://h20195.www2.hpe.com/V2/getpdf.aspx/4AA4-7673ENW.pdf>. */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 +#endif + +#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST8_TYPE__ yytype_uint8; +#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST8_MAX <= INT_MAX) +typedef uint_least8_t yytype_uint8; +#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX +typedef unsigned char yytype_uint8; +#else +typedef short yytype_uint8; +#endif + +#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST16_TYPE__ yytype_uint16; +#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST16_MAX <= INT_MAX) +typedef uint_least16_t yytype_uint16; +#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX +typedef unsigned short yytype_uint16; +#else +typedef int yytype_uint16; +#endif + +#ifndef YYPTRDIFF_T +# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ +# define YYPTRDIFF_T __PTRDIFF_TYPE__ +# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ +# elif defined PTRDIFF_MAX +# ifndef ptrdiff_t +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# endif +# define YYPTRDIFF_T ptrdiff_t +# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX +# else +# define YYPTRDIFF_T long +# define YYPTRDIFF_MAXIMUM LONG_MAX +# endif +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned +# endif +#endif + +#define YYSIZE_MAXIMUM \ + YY_CAST (YYPTRDIFF_T, \ + (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \ + ? YYPTRDIFF_MAXIMUM \ + : YY_CAST (YYSIZE_T, -1))) + +#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) + + +/* Stored state numbers (used for stacks). */ +typedef yytype_int8 yy_state_t; + +/* State numbers in computations. */ +typedef int yy_state_fast_t; + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include <libintl.h> /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif + + +#ifndef YY_ATTRIBUTE_PURE +# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define YY_ATTRIBUTE_PURE +# endif +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +# else +# define YY_ATTRIBUTE_UNUSED +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YY_USE(E) ((void) (E)) +#else +# define YY_USE(E) /* empty */ +#endif + +#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + +#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ +# define YY_IGNORE_USELESS_CAST_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") +# define YY_IGNORE_USELESS_CAST_END \ + _Pragma ("GCC diagnostic pop") +#endif +#ifndef YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_END +#endif + + +#define YY_ASSERT(E) ((void) (0 && (E))) + +#if !defined yyoverflow + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include <alloca.h> /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include <malloc.h> /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* !defined yyoverflow */ + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yy_state_t yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYPTRDIFF_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / YYSIZEOF (*yyptr); \ + } \ + while (0) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYPTRDIFF_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 8 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 12 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 7 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 4 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 9 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 14 + +/* YYMAXUTOK -- Last valid token kind. */ +#define YYMAXUTOK 261 + + +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, with out-of-bounds checking. */ +#define YYTRANSLATE(YYX) \ + (0 <= (YYX) && (YYX) <= YYMAXUTOK \ + ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \ + : YYSYMBOL_YYUNDEF) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex. */ +static const yytype_int8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6 +}; + +#if YYDEBUG + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_uint8 yyrline[] = +{ + 0, 66, 66, 78, 96, 106, 116, 124, 133, 144 +}; +#endif + +/** Accessing symbol of state STATE. */ +#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State]) + +#if YYDEBUG || 0 +/* The user-facing name of the symbol whose (internal) number is + YYSYMBOL. No bounds checking. */ +static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; + +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "\"end of file\"", "error", "\"invalid token\"", "SEGFLOAT", "RANGE", + "PLUMIN", "EXTENSION", "$accept", "range", "boundary", "deviation", YY_NULLPTR +}; + +static const char * +yysymbol_name (yysymbol_kind_t yysymbol) +{ + return yytname[yysymbol]; +} +#endif + +#ifdef YYPRINT +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ +static const yytype_int16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261 +}; +#endif + +#define YYPACT_NINF (-3) + +#define yypact_value_is_default(Yyn) \ + ((Yyn) == YYPACT_NINF) + +#define YYTABLE_NINF (-1) + +#define yytable_value_is_error(Yyn) \ + 0 + + /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int8 yypact[] = +{ + -1, -3, 3, 1, 8, 6, -3, -3, -3, 3, + 9, -3, -3, -3 +}; + + /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_int8 yydefact[] = +{ + 0, 7, 0, 0, 0, 6, 5, 8, 1, 4, + 0, 3, 9, 2 +}; + + /* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -3, -3, -2, -3 +}; + + /* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = +{ + 0, 4, 5, 13 +}; + + /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_int8 yytable[] = +{ + 6, 0, 1, 2, 7, 3, 1, 11, 8, 3, + 9, 10, 12 +}; + +static const yytype_int8 yycheck[] = +{ + 2, -1, 3, 4, 3, 6, 3, 9, 0, 6, + 4, 5, 3 +}; + + /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_int8 yystos[] = +{ + 0, 3, 4, 6, 8, 9, 9, 3, 0, 4, + 5, 9, 3, 10 +}; + + /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_int8 yyr1[] = +{ + 0, 7, 8, 8, 8, 8, 8, 9, 9, 10 +}; + + /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_int8 yyr2[] = +{ + 0, 2, 3, 3, 2, 2, 1, 1, 2, 1 +}; + + +enum { YYENOMEM = -2 }; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (result, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (0) + +/* Backward compatibility with an undocumented macro. + Use YYerror or YYUNDEF. */ +#define YYERRCODE YYUNDEF + + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +/* This macro is provided for backward compatibility. */ +# ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif + + +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Kind, Value, result); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + + +/*-----------------------------------. +| Print this symbol's value on YYO. | +`-----------------------------------*/ + +static void +yy_symbol_value_print (FILE *yyo, + yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, SEG *result) +{ + FILE *yyoutput = yyo; + YY_USE (yyoutput); + YY_USE (result); + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yykind < YYNTOKENS) + YYPRINT (yyo, yytoknum[yykind], *yyvaluep); +# endif + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YY_USE (yykind); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + +/*---------------------------. +| Print this symbol on YYO. | +`---------------------------*/ + +static void +yy_symbol_print (FILE *yyo, + yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, SEG *result) +{ + YYFPRINTF (yyo, "%s %s (", + yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind)); + + yy_symbol_value_print (yyo, yykind, yyvaluep, result); + YYFPRINTF (yyo, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +static void +yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop) +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +static void +yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, + int yyrule, SEG *result) +{ + int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; + int yyi; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), + &yyvsp[(yyi + 1) - (yynrhs)], result); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, Rule, result); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) ((void) 0) +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + + + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +yydestruct (const char *yymsg, + yysymbol_kind_t yykind, YYSTYPE *yyvaluep, SEG *result) +{ + YY_USE (yyvaluep); + YY_USE (result); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YY_USE (yykind); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + +/* Lookahead token kind. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; +/* Number of syntax errors so far. */ +int yynerrs; + + + + +/*----------. +| yyparse. | +`----------*/ + +int +yyparse (SEG *result) +{ + yy_state_fast_t yystate = 0; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus = 0; + + /* Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* Their size. */ + YYPTRDIFF_T yystacksize = YYINITDEPTH; + + /* The state stack: array, bottom, top. */ + yy_state_t yyssa[YYINITDEPTH]; + yy_state_t *yyss = yyssa; + yy_state_t *yyssp = yyss; + + /* The semantic value stack: array, bottom, top. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp = yyvs; + + int yyn; + /* The return value of yyparse. */ + int yyresult; + /* Lookahead symbol kind. */ + yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yychar = YYEMPTY; /* Cause a token to be read. */ + goto yysetstate; + + +/*------------------------------------------------------------. +| yynewstate -- push a new state, which is found in yystate. | +`------------------------------------------------------------*/ +yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + +/*--------------------------------------------------------------------. +| yysetstate -- set current state (the top of the stack) to yystate. | +`--------------------------------------------------------------------*/ +yysetstate: + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); + YY_IGNORE_USELESS_CAST_BEGIN + *yyssp = YY_CAST (yy_state_t, yystate); + YY_IGNORE_USELESS_CAST_END + YY_STACK_PRINT (yyss, yyssp); + + if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE + goto yyexhaustedlab; +#else + { + /* Get the current used size of the three stacks, in elements. */ + YYPTRDIFF_T yysize = yyssp - yyss + 1; + +# if defined yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + yy_state_t *yyss1 = yyss; + YYSTYPE *yyvs1 = yyvs; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * YYSIZEOF (*yyssp), + &yyvs1, yysize * YYSIZEOF (*yyvsp), + &yystacksize); + yyss = yyss1; + yyvs = yyvs1; + } +# else /* defined YYSTACK_RELOCATE */ + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yy_state_t *yyss1 = yyss; + union yyalloc *yyptr = + YY_CAST (union yyalloc *, + YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YY_IGNORE_USELESS_CAST_BEGIN + YYDPRINTF ((stderr, "Stack size increased to %ld\n", + YY_CAST (long, yystacksize))); + YY_IGNORE_USELESS_CAST_END + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token\n")); + yychar = yylex (); + } + + if (yychar <= YYEOF) + { + yychar = YYEOF; + yytoken = YYSYMBOL_YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else if (yychar == YYerror) + { + /* The scanner already issued an error message, process directly + to error recovery. But do not keep the error token as + lookahead, it is too special and may lead us to an endless + loop in error recovery. */ + yychar = YYUNDEF; + yytoken = YYSYMBOL_YYerror; + goto yyerrlab1; + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + /* Discard the shifted token. */ + yychar = YYEMPTY; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + '$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: /* range: boundary PLUMIN deviation */ +#line 67 "segparse.y" + { + result->lower = (yyvsp[-2].bnd).val - (yyvsp[0].bnd).val; + result->upper = (yyvsp[-2].bnd).val + (yyvsp[0].bnd).val; + sprintf(strbuf, "%g", result->lower); + result->l_sigd = Max(sig_digits(strbuf), Max((yyvsp[-2].bnd).sigd, (yyvsp[0].bnd).sigd)); + sprintf(strbuf, "%g", result->upper); + result->u_sigd = Max(sig_digits(strbuf), Max((yyvsp[-2].bnd).sigd, (yyvsp[0].bnd).sigd)); + result->l_ext = '\0'; + result->u_ext = '\0'; + } +#line 1176 "segparse.c" + break; + + case 3: /* range: boundary RANGE boundary */ +#line 79 "segparse.y" + { + result->lower = (yyvsp[-2].bnd).val; + result->upper = (yyvsp[0].bnd).val; + if ( result->lower > result->upper ) { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("swapped boundaries: %g is greater than %g", + result->lower, result->upper))); + + YYERROR; + } + result->l_sigd = (yyvsp[-2].bnd).sigd; + result->u_sigd = (yyvsp[0].bnd).sigd; + result->l_ext = ( (yyvsp[-2].bnd).ext ? (yyvsp[-2].bnd).ext : '\0' ); + result->u_ext = ( (yyvsp[0].bnd).ext ? (yyvsp[0].bnd).ext : '\0' ); + } +#line 1197 "segparse.c" + break; + + case 4: /* range: boundary RANGE */ +#line 97 "segparse.y" + { + result->lower = (yyvsp[-1].bnd).val; + result->upper = HUGE_VAL; + result->l_sigd = (yyvsp[-1].bnd).sigd; + result->u_sigd = 0; + result->l_ext = ( (yyvsp[-1].bnd).ext ? (yyvsp[-1].bnd).ext : '\0' ); + result->u_ext = '-'; + } +#line 1210 "segparse.c" + break; + + case 5: /* range: RANGE boundary */ +#line 107 "segparse.y" + { + result->lower = -HUGE_VAL; + result->upper = (yyvsp[0].bnd).val; + result->l_sigd = 0; + result->u_sigd = (yyvsp[0].bnd).sigd; + result->l_ext = '-'; + result->u_ext = ( (yyvsp[0].bnd).ext ? (yyvsp[0].bnd).ext : '\0' ); + } +#line 1223 "segparse.c" + break; + + case 6: /* range: boundary */ +#line 117 "segparse.y" + { + result->lower = result->upper = (yyvsp[0].bnd).val; + result->l_sigd = result->u_sigd = (yyvsp[0].bnd).sigd; + result->l_ext = result->u_ext = ( (yyvsp[0].bnd).ext ? (yyvsp[0].bnd).ext : '\0' ); + } +#line 1233 "segparse.c" + break; + + case 7: /* boundary: SEGFLOAT */ +#line 125 "segparse.y" + { + /* temp variable avoids a gcc 3.3.x bug on Sparc64 */ + float val = seg_atof((yyvsp[0].text)); + + (yyval.bnd).ext = '\0'; + (yyval.bnd).sigd = sig_digits((yyvsp[0].text)); + (yyval.bnd).val = val; + } +#line 1246 "segparse.c" + break; + + case 8: /* boundary: EXTENSION SEGFLOAT */ +#line 134 "segparse.y" + { + /* temp variable avoids a gcc 3.3.x bug on Sparc64 */ + float val = seg_atof((yyvsp[0].text)); + + (yyval.bnd).ext = (yyvsp[-1].text)[0]; + (yyval.bnd).sigd = sig_digits((yyvsp[0].text)); + (yyval.bnd).val = val; + } +#line 1259 "segparse.c" + break; + + case 9: /* deviation: SEGFLOAT */ +#line 145 "segparse.y" + { + /* temp variable avoids a gcc 3.3.x bug on Sparc64 */ + float val = seg_atof((yyvsp[0].text)); + + (yyval.bnd).ext = '\0'; + (yyval.bnd).sigd = sig_digits((yyvsp[0].text)); + (yyval.bnd).val = val; + } +#line 1272 "segparse.c" + break; + + +#line 1276 "segparse.c" + + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + + *++yyvsp = yyval; + + /* Now 'shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *yyssp; + yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp + ? yytable[yyi] + : yydefgoto[yylhs]); + } + + goto yynewstate; + + +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; + yyerror (result, YY_("syntax error")); + } + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval, result); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + /* Pacify compilers when the user code never invokes YYERROR and the + label yyerrorlab therefore never appears in user code. */ + if (0) + YYERROR; + + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + /* Pop stack until we find a state that shifts the error token. */ + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYSYMBOL_YYerror; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + YY_ACCESSING_SYMBOL (yystate), yyvsp, result); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + + +#if !defined yyoverflow +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (result, YY_("memory exhausted")); + yyresult = 2; + goto yyreturn; +#endif + + +/*-------------------------------------------------------. +| yyreturn -- parsing is finished, clean up and return. | +`-------------------------------------------------------*/ +yyreturn: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, result); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, result); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + + return yyresult; +} + +#line 155 "segparse.y" + + + +static float +seg_atof(const char *value) +{ + Datum datum; + + datum = DirectFunctionCall1(float4in, CStringGetDatum(value)); + return DatumGetFloat4(datum); +} + +static int +sig_digits(const char *value) +{ + int n = significant_digits(value); + + /* Clamp, to ensure value will fit in sigd fields */ + return Min(n, FLT_DIG); +} + + +#include "segscan.c" diff --git a/contrib/seg/segparse.y b/contrib/seg/segparse.y new file mode 100644 index 0000000..0dc6bb6 --- /dev/null +++ b/contrib/seg/segparse.y @@ -0,0 +1,177 @@ +%{ +/* contrib/seg/segparse.y */ + +#include "postgres.h" + +#include <float.h> +#include <math.h> + +#include "fmgr.h" +#include "utils/builtins.h" + +#include "segdata.h" + +/* + * Bison doesn't allocate anything that needs to live across parser calls, + * so we can easily have it use palloc instead of malloc. This prevents + * memory leaks if we error out during parsing. Note this only works with + * bison >= 2.0. However, in bison 1.875 the default is to use alloca() + * if possible, so there's not really much problem anyhow, at least if + * you're building with gcc. + */ +#define YYMALLOC palloc +#define YYFREE pfree + +static float seg_atof(const char *value); + +static int sig_digits(const char *value); + +static char strbuf[25] = { + '0', '0', '0', '0', '0', + '0', '0', '0', '0', '0', + '0', '0', '0', '0', '0', + '0', '0', '0', '0', '0', + '0', '0', '0', '0', '\0' +}; + +%} + +/* BISON Declarations */ +%parse-param {SEG *result} +%expect 0 +%name-prefix="seg_yy" + +%union +{ + struct BND + { + float val; + char ext; + char sigd; + } bnd; + char *text; +} +%token <text> SEGFLOAT +%token <text> RANGE +%token <text> PLUMIN +%token <text> EXTENSION +%type <bnd> boundary +%type <bnd> deviation +%start range + +/* Grammar follows */ +%% + + +range: boundary PLUMIN deviation + { + result->lower = $1.val - $3.val; + result->upper = $1.val + $3.val; + sprintf(strbuf, "%g", result->lower); + result->l_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd)); + sprintf(strbuf, "%g", result->upper); + result->u_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd)); + result->l_ext = '\0'; + result->u_ext = '\0'; + } + + | boundary RANGE boundary + { + result->lower = $1.val; + result->upper = $3.val; + if ( result->lower > result->upper ) { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("swapped boundaries: %g is greater than %g", + result->lower, result->upper))); + + YYERROR; + } + result->l_sigd = $1.sigd; + result->u_sigd = $3.sigd; + result->l_ext = ( $1.ext ? $1.ext : '\0' ); + result->u_ext = ( $3.ext ? $3.ext : '\0' ); + } + + | boundary RANGE + { + result->lower = $1.val; + result->upper = HUGE_VAL; + result->l_sigd = $1.sigd; + result->u_sigd = 0; + result->l_ext = ( $1.ext ? $1.ext : '\0' ); + result->u_ext = '-'; + } + + | RANGE boundary + { + result->lower = -HUGE_VAL; + result->upper = $2.val; + result->l_sigd = 0; + result->u_sigd = $2.sigd; + result->l_ext = '-'; + result->u_ext = ( $2.ext ? $2.ext : '\0' ); + } + + | boundary + { + result->lower = result->upper = $1.val; + result->l_sigd = result->u_sigd = $1.sigd; + result->l_ext = result->u_ext = ( $1.ext ? $1.ext : '\0' ); + } + ; + +boundary: SEGFLOAT + { + /* temp variable avoids a gcc 3.3.x bug on Sparc64 */ + float val = seg_atof($1); + + $$.ext = '\0'; + $$.sigd = sig_digits($1); + $$.val = val; + } + | EXTENSION SEGFLOAT + { + /* temp variable avoids a gcc 3.3.x bug on Sparc64 */ + float val = seg_atof($2); + + $$.ext = $1[0]; + $$.sigd = sig_digits($2); + $$.val = val; + } + ; + +deviation: SEGFLOAT + { + /* temp variable avoids a gcc 3.3.x bug on Sparc64 */ + float val = seg_atof($1); + + $$.ext = '\0'; + $$.sigd = sig_digits($1); + $$.val = val; + } + ; + +%% + + +static float +seg_atof(const char *value) +{ + Datum datum; + + datum = DirectFunctionCall1(float4in, CStringGetDatum(value)); + return DatumGetFloat4(datum); +} + +static int +sig_digits(const char *value) +{ + int n = significant_digits(value); + + /* Clamp, to ensure value will fit in sigd fields */ + return Min(n, FLT_DIG); +} + + +#include "segscan.c" diff --git a/contrib/seg/segscan.c b/contrib/seg/segscan.c new file mode 100644 index 0000000..792cb64 --- /dev/null +++ b/contrib/seg/segscan.c @@ -0,0 +1,2095 @@ +#line 2 "segscan.c" + +#line 4 "segscan.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define yy_create_buffer seg_yy_create_buffer +#define yy_delete_buffer seg_yy_delete_buffer +#define yy_scan_buffer seg_yy_scan_buffer +#define yy_scan_string seg_yy_scan_string +#define yy_scan_bytes seg_yy_scan_bytes +#define yy_init_buffer seg_yy_init_buffer +#define yy_flush_buffer seg_yy_flush_buffer +#define yy_load_buffer_state seg_yy_load_buffer_state +#define yy_switch_to_buffer seg_yy_switch_to_buffer +#define yypush_buffer_state seg_yypush_buffer_state +#define yypop_buffer_state seg_yypop_buffer_state +#define yyensure_buffer_stack seg_yyensure_buffer_stack +#define yy_flex_debug seg_yy_flex_debug +#define yyin seg_yyin +#define yyleng seg_yyleng +#define yylex seg_yylex +#define yylineno seg_yylineno +#define yyout seg_yyout +#define yyrestart seg_yyrestart +#define yytext seg_yytext +#define yywrap seg_yywrap +#define yyalloc seg_yyalloc +#define yyrealloc seg_yyrealloc +#define yyfree seg_yyfree + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 4 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +#ifdef yy_create_buffer +#define seg_yy_create_buffer_ALREADY_DEFINED +#else +#define yy_create_buffer seg_yy_create_buffer +#endif + +#ifdef yy_delete_buffer +#define seg_yy_delete_buffer_ALREADY_DEFINED +#else +#define yy_delete_buffer seg_yy_delete_buffer +#endif + +#ifdef yy_scan_buffer +#define seg_yy_scan_buffer_ALREADY_DEFINED +#else +#define yy_scan_buffer seg_yy_scan_buffer +#endif + +#ifdef yy_scan_string +#define seg_yy_scan_string_ALREADY_DEFINED +#else +#define yy_scan_string seg_yy_scan_string +#endif + +#ifdef yy_scan_bytes +#define seg_yy_scan_bytes_ALREADY_DEFINED +#else +#define yy_scan_bytes seg_yy_scan_bytes +#endif + +#ifdef yy_init_buffer +#define seg_yy_init_buffer_ALREADY_DEFINED +#else +#define yy_init_buffer seg_yy_init_buffer +#endif + +#ifdef yy_flush_buffer +#define seg_yy_flush_buffer_ALREADY_DEFINED +#else +#define yy_flush_buffer seg_yy_flush_buffer +#endif + +#ifdef yy_load_buffer_state +#define seg_yy_load_buffer_state_ALREADY_DEFINED +#else +#define yy_load_buffer_state seg_yy_load_buffer_state +#endif + +#ifdef yy_switch_to_buffer +#define seg_yy_switch_to_buffer_ALREADY_DEFINED +#else +#define yy_switch_to_buffer seg_yy_switch_to_buffer +#endif + +#ifdef yypush_buffer_state +#define seg_yypush_buffer_state_ALREADY_DEFINED +#else +#define yypush_buffer_state seg_yypush_buffer_state +#endif + +#ifdef yypop_buffer_state +#define seg_yypop_buffer_state_ALREADY_DEFINED +#else +#define yypop_buffer_state seg_yypop_buffer_state +#endif + +#ifdef yyensure_buffer_stack +#define seg_yyensure_buffer_stack_ALREADY_DEFINED +#else +#define yyensure_buffer_stack seg_yyensure_buffer_stack +#endif + +#ifdef yylex +#define seg_yylex_ALREADY_DEFINED +#else +#define yylex seg_yylex +#endif + +#ifdef yyrestart +#define seg_yyrestart_ALREADY_DEFINED +#else +#define yyrestart seg_yyrestart +#endif + +#ifdef yylex_init +#define seg_yylex_init_ALREADY_DEFINED +#else +#define yylex_init seg_yylex_init +#endif + +#ifdef yylex_init_extra +#define seg_yylex_init_extra_ALREADY_DEFINED +#else +#define yylex_init_extra seg_yylex_init_extra +#endif + +#ifdef yylex_destroy +#define seg_yylex_destroy_ALREADY_DEFINED +#else +#define yylex_destroy seg_yylex_destroy +#endif + +#ifdef yyget_debug +#define seg_yyget_debug_ALREADY_DEFINED +#else +#define yyget_debug seg_yyget_debug +#endif + +#ifdef yyset_debug +#define seg_yyset_debug_ALREADY_DEFINED +#else +#define yyset_debug seg_yyset_debug +#endif + +#ifdef yyget_extra +#define seg_yyget_extra_ALREADY_DEFINED +#else +#define yyget_extra seg_yyget_extra +#endif + +#ifdef yyset_extra +#define seg_yyset_extra_ALREADY_DEFINED +#else +#define yyset_extra seg_yyset_extra +#endif + +#ifdef yyget_in +#define seg_yyget_in_ALREADY_DEFINED +#else +#define yyget_in seg_yyget_in +#endif + +#ifdef yyset_in +#define seg_yyset_in_ALREADY_DEFINED +#else +#define yyset_in seg_yyset_in +#endif + +#ifdef yyget_out +#define seg_yyget_out_ALREADY_DEFINED +#else +#define yyget_out seg_yyget_out +#endif + +#ifdef yyset_out +#define seg_yyset_out_ALREADY_DEFINED +#else +#define yyset_out seg_yyset_out +#endif + +#ifdef yyget_leng +#define seg_yyget_leng_ALREADY_DEFINED +#else +#define yyget_leng seg_yyget_leng +#endif + +#ifdef yyget_text +#define seg_yyget_text_ALREADY_DEFINED +#else +#define yyget_text seg_yyget_text +#endif + +#ifdef yyget_lineno +#define seg_yyget_lineno_ALREADY_DEFINED +#else +#define yyget_lineno seg_yyget_lineno +#endif + +#ifdef yyset_lineno +#define seg_yyset_lineno_ALREADY_DEFINED +#else +#define yyset_lineno seg_yyset_lineno +#endif + +#ifdef yywrap +#define seg_yywrap_ALREADY_DEFINED +#else +#define yywrap seg_yywrap +#endif + +#ifdef yyalloc +#define seg_yyalloc_ALREADY_DEFINED +#else +#define yyalloc seg_yyalloc +#endif + +#ifdef yyrealloc +#define seg_yyrealloc_ALREADY_DEFINED +#else +#define yyrealloc seg_yyrealloc +#endif + +#ifdef yyfree +#define seg_yyfree_ALREADY_DEFINED +#else +#define yyfree seg_yyfree +#endif + +#ifdef yytext +#define seg_yytext_ALREADY_DEFINED +#else +#define yytext seg_yytext +#endif + +#ifdef yyleng +#define seg_yyleng_ALREADY_DEFINED +#else +#define yyleng seg_yyleng +#endif + +#ifdef yyin +#define seg_yyin_ALREADY_DEFINED +#else +#define yyin seg_yyin +#endif + +#ifdef yyout +#define seg_yyout_ALREADY_DEFINED +#else +#define yyout seg_yyout +#endif + +#ifdef yy_flex_debug +#define seg_yy_flex_debug_ALREADY_DEFINED +#else +#define yy_flex_debug seg_yy_flex_debug +#endif + +#ifdef yylineno +#define seg_yylineno_ALREADY_DEFINED +#else +#define yylineno seg_yylineno +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* begin standard C++ headers. */ + +/* TODO: this is always defined, so inline it */ +#define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +#define yynoreturn __attribute__((__noreturn__)) +#else +#define yynoreturn +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an + * integer in range [0..255] for use as an array index. + */ +#define YY_SC_TO_UI(c) ((YY_CHAR) (c)) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +extern int yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + #define YY_LINENO_REWIND_TO(ptr) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + int yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = NULL; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart ( FILE *input_file ); +void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size ); +void yy_delete_buffer ( YY_BUFFER_STATE b ); +void yy_flush_buffer ( YY_BUFFER_STATE b ); +void yypush_buffer_state ( YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state ( void ); + +static void yyensure_buffer_stack ( void ); +static void yy_load_buffer_state ( void ); +static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file ); +#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size ); +YY_BUFFER_STATE yy_scan_string ( const char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len ); + +void *yyalloc ( yy_size_t ); +void *yyrealloc ( void *, yy_size_t ); +void yyfree ( void * ); + +#define yy_new_buffer yy_create_buffer +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer( yyin, YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer( yyin, YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define seg_yywrap() (/*CONSTCOND*/1) +#define YY_SKIP_YYWRAP +typedef flex_uint8_t YY_CHAR; + +FILE *yyin = NULL, *yyout = NULL; + +typedef int yy_state_type; + +extern int yylineno; +int yylineno = 1; + +extern char *yytext; +#ifdef yytext_ptr +#undef yytext_ptr +#endif +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state ( void ); +static yy_state_type yy_try_NUL_trans ( yy_state_type current_state ); +static int yy_get_next_buffer ( void ); +static void yynoreturn yy_fatal_error ( const char* msg ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; +#define YY_NUM_RULES 9 +#define YY_END_OF_BUFFER 10 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static const flex_int16_t yy_accept[30] = + { 0, + 0, 0, 10, 8, 7, 7, 8, 8, 8, 8, + 3, 4, 5, 6, 7, 0, 0, 3, 1, 0, + 0, 0, 0, 1, 3, 0, 3, 2, 0 + } ; + +static const YY_CHAR yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 1, 4, 5, + 6, 1, 7, 1, 8, 9, 1, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 1, 1, 11, + 1, 12, 1, 1, 1, 1, 1, 1, 13, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 14, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static const YY_CHAR yy_meta[15] = + { 0, + 1, 1, 1, 1, 1, 1, 2, 2, 1, 2, + 1, 1, 1, 1 + } ; + +static const flex_int16_t yy_base[31] = + { 0, + 0, 0, 40, 41, 13, 15, 32, 31, 27, 27, + 10, 41, 41, 41, 19, 27, 26, 0, 24, 22, + 21, 26, 23, 41, 14, 18, 16, 41, 41, 23 + } ; + +static const flex_int16_t yy_def[31] = + { 0, + 29, 1, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 11, 29, 29, + 30, 29, 29, 29, 29, 29, 29, 29, 0, 29 + } ; + +static const flex_int16_t yy_nxt[56] = + { 0, + 4, 5, 6, 7, 8, 4, 9, 9, 10, 11, + 12, 13, 4, 14, 15, 15, 15, 15, 20, 18, + 15, 15, 21, 25, 26, 27, 21, 27, 28, 28, + 27, 25, 24, 23, 22, 19, 18, 17, 16, 29, + 3, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29 + } ; + +static const flex_int16_t yy_chk[56] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 5, 5, 6, 6, 11, 11, + 15, 15, 11, 25, 30, 27, 25, 26, 23, 22, + 21, 20, 19, 17, 16, 10, 9, 8, 7, 3, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "segscan.l" +#line 2 "segscan.l" +/* + * A scanner for EMP-style numeric ranges + */ + +/* LCOV_EXCL_START */ + +/* No reason to constrain amount of data slurped */ +#define YY_READ_BUF_SIZE 16777216 + +/* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */ +#undef fprintf +#define fprintf(file, fmt, msg) fprintf_to_ereport(fmt, msg) + +static void +fprintf_to_ereport(const char *fmt, const char *msg) +{ + ereport(ERROR, (errmsg_internal("%s", msg))); +} + +/* Handles to the buffer that the lexer uses internally */ +static YY_BUFFER_STATE scanbufhandle; +static char *scanbuf; +static int scanbuflen; +#line 745 "segscan.c" +#define YY_NO_INPUT 1 +#line 747 "segscan.c" + +#define INITIAL 0 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include <unistd.h> +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals ( void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy ( void ); + +int yyget_debug ( void ); + +void yyset_debug ( int debug_flag ); + +YY_EXTRA_TYPE yyget_extra ( void ); + +void yyset_extra ( YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in ( void ); + +void yyset_in ( FILE * _in_str ); + +FILE *yyget_out ( void ); + +void yyset_out ( FILE * _out_str ); + + int yyget_leng ( void ); + +char *yyget_text ( void ); + +int yyget_lineno ( void ); + +void yyset_lineno ( int _line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap ( void ); +#else +extern int yywrap ( void ); +#endif +#endif + +#ifndef YY_NO_UNPUT + +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy ( char *, const char *, int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen ( const char * ); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput ( void ); +#else +static int input ( void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + int n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK /*LINTED*/break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer( yyin, YY_BUF_SIZE ); + } + + yy_load_buffer_state( ); + } + + { +#line 43 "segscan.l" + + +#line 965 "segscan.c" + + while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of yytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + do + { + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 30 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + ++yy_cp; + } + while ( yy_current_state != 29 ); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 45 "segscan.l" +yylval.text = yytext; return RANGE; + YY_BREAK +case 2: +YY_RULE_SETUP +#line 46 "segscan.l" +yylval.text = yytext; return PLUMIN; + YY_BREAK +case 3: +YY_RULE_SETUP +#line 47 "segscan.l" +yylval.text = yytext; return SEGFLOAT; + YY_BREAK +case 4: +YY_RULE_SETUP +#line 48 "segscan.l" +yylval.text = "<"; return EXTENSION; + YY_BREAK +case 5: +YY_RULE_SETUP +#line 49 "segscan.l" +yylval.text = ">"; return EXTENSION; + YY_BREAK +case 6: +YY_RULE_SETUP +#line 50 "segscan.l" +yylval.text = "~"; return EXTENSION; + YY_BREAK +case 7: +/* rule 7 can match eol */ +YY_RULE_SETUP +#line 51 "segscan.l" +/* discard spaces */ + YY_BREAK +case 8: +YY_RULE_SETUP +#line 52 "segscan.l" +return yytext[0]; /* alert parser of the garbage */ + YY_BREAK +case 9: +YY_RULE_SETUP +#line 54 "segscan.l" +YY_FATAL_ERROR( "flex scanner jammed" ); + YY_BREAK +#line 1064 "segscan.c" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( yywrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of user's declarations */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = (yytext_ptr); + int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1); + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc( (void *) b->yy_ch_buf, + (yy_size_t) (b->yy_buf_size + 2) ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = NULL; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( + (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + /* "- 2" to take care of EOB's */ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + yy_state_type yy_current_state; + char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 30 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + int yy_is_jam; + char *yy_cp = (yy_c_buf_p); + + YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 30 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + yy_is_jam = (yy_current_state == 29); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_UNPUT + +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (int) ((yy_c_buf_p) - (yytext_ptr)); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( ) ) + return 0; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer( yyin, YY_BUF_SIZE ); + } + + yy_init_buffer( YY_CURRENT_BUFFER, input_file ); + yy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree( (void *) b->yy_ch_buf ); + + yyfree( (void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + yy_size_t num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + yy_size_t grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return NULL; + + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = NULL; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (const char * yystr ) +{ + + return yy_scan_bytes( yystr, (int) strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = (yy_size_t) (_yybytes_len + 2); + buf = (char *) yyalloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yynoreturn yy_fatal_error (const char* msg ) +{ + fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} + +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} + +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} + +/** Get the length of the current token. + * + */ +int yyget_leng (void) +{ + return yyleng; +} + +/** Get the current token. + * + */ + +char *yyget_text (void) +{ + return yytext; +} + +/** Set the current line number. + * @param _line_number line number + * + */ +void yyset_lineno (int _line_number ) +{ + + yylineno = _line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param _in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * _in_str ) +{ + yyin = _in_str ; +} + +void yyset_out (FILE * _out_str ) +{ + yyout = _out_str ; +} + +int yyget_debug (void) +{ + return yy_flex_debug; +} + +void yyset_debug (int _bdebug ) +{ + yy_flex_debug = _bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = NULL; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = NULL; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = NULL; + yyout = NULL; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer( YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, const char * s2, int n ) +{ + + int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (const char * s ) +{ + int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size ) +{ + return malloc(size); +} + +void *yyrealloc (void * ptr, yy_size_t size ) +{ + + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return realloc(ptr, size); +} + +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 54 "segscan.l" + + +/* LCOV_EXCL_STOP */ + +void +yyerror(SEG *result, const char *message) +{ + if (*yytext == YY_END_OF_BUFFER_CHAR) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("bad seg representation"), + /* translator: %s is typically "syntax error" */ + errdetail("%s at end of input", message))); + } + else + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("bad seg representation"), + /* translator: first %s is typically "syntax error" */ + errdetail("%s at or near \"%s\"", message, yytext))); + } +} + + +/* + * Called before any actual parsing is done + */ +void +seg_scanner_init(const char *str) +{ + Size slen = strlen(str); + + /* + * Might be left over after ereport() + */ + if (YY_CURRENT_BUFFER) + yy_delete_buffer(YY_CURRENT_BUFFER); + + /* + * Make a scan buffer with special termination needed by flex. + */ + scanbuflen = slen; + scanbuf = palloc(slen + 2); + memcpy(scanbuf, str, slen); + scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR; + scanbufhandle = yy_scan_buffer(scanbuf, slen + 2); + + BEGIN(INITIAL); +} + + +/* + * Called after parsing is done to clean up after seg_scanner_init() + */ +void +seg_scanner_finish(void) +{ + yy_delete_buffer(scanbufhandle); + pfree(scanbuf); +} + diff --git a/contrib/seg/segscan.l b/contrib/seg/segscan.l new file mode 100644 index 0000000..5f6595e --- /dev/null +++ b/contrib/seg/segscan.l @@ -0,0 +1,115 @@ +%{ +/* + * A scanner for EMP-style numeric ranges + */ + +/* LCOV_EXCL_START */ + +/* No reason to constrain amount of data slurped */ +#define YY_READ_BUF_SIZE 16777216 + +/* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */ +#undef fprintf +#define fprintf(file, fmt, msg) fprintf_to_ereport(fmt, msg) + +static void +fprintf_to_ereport(const char *fmt, const char *msg) +{ + ereport(ERROR, (errmsg_internal("%s", msg))); +} + +/* Handles to the buffer that the lexer uses internally */ +static YY_BUFFER_STATE scanbufhandle; +static char *scanbuf; +static int scanbuflen; +%} + +%option 8bit +%option never-interactive +%option nodefault +%option noinput +%option nounput +%option noyywrap +%option warn +%option prefix="seg_yy" + + +range (\.\.)(\.)? +plumin (\'\+\-\')|(\(\+\-)\) +integer [+-]?[0-9]+ +real [+-]?[0-9]+\.[0-9]+ +float ({integer}|{real})([eE]{integer})? + +%% + +{range} yylval.text = yytext; return RANGE; +{plumin} yylval.text = yytext; return PLUMIN; +{float} yylval.text = yytext; return SEGFLOAT; +\< yylval.text = "<"; return EXTENSION; +\> yylval.text = ">"; return EXTENSION; +\~ yylval.text = "~"; return EXTENSION; +[ \t\n\r\f]+ /* discard spaces */ +. return yytext[0]; /* alert parser of the garbage */ + +%% + +/* LCOV_EXCL_STOP */ + +void +yyerror(SEG *result, const char *message) +{ + if (*yytext == YY_END_OF_BUFFER_CHAR) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("bad seg representation"), + /* translator: %s is typically "syntax error" */ + errdetail("%s at end of input", message))); + } + else + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("bad seg representation"), + /* translator: first %s is typically "syntax error" */ + errdetail("%s at or near \"%s\"", message, yytext))); + } +} + + +/* + * Called before any actual parsing is done + */ +void +seg_scanner_init(const char *str) +{ + Size slen = strlen(str); + + /* + * Might be left over after ereport() + */ + if (YY_CURRENT_BUFFER) + yy_delete_buffer(YY_CURRENT_BUFFER); + + /* + * Make a scan buffer with special termination needed by flex. + */ + scanbuflen = slen; + scanbuf = palloc(slen + 2); + memcpy(scanbuf, str, slen); + scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR; + scanbufhandle = yy_scan_buffer(scanbuf, slen + 2); + + BEGIN(INITIAL); +} + + +/* + * Called after parsing is done to clean up after seg_scanner_init() + */ +void +seg_scanner_finish(void) +{ + yy_delete_buffer(scanbufhandle); + pfree(scanbuf); +} diff --git a/contrib/seg/sort-segments.pl b/contrib/seg/sort-segments.pl new file mode 100755 index 0000000..67a227b --- /dev/null +++ b/contrib/seg/sort-segments.pl @@ -0,0 +1,30 @@ +#!/usr/bin/perl + +# Copyright (c) 2021-2022, PostgreSQL Global Development Group + +# this script will sort any table with the segment data type in its last column + +use strict; +use warnings; + +my @rows; + +while (<>) +{ + chomp; + push @rows, $_; +} + +foreach ( + sort { + my @ar = split("\t", $a); + my $valA = pop @ar; + $valA =~ s/[~<> ]+//g; + @ar = split("\t", $b); + my $valB = pop @ar; + $valB =~ s/[~<> ]+//g; + $valA <=> $valB + } @rows) +{ + print "$_\n"; +} diff --git a/contrib/seg/sql/security.sql b/contrib/seg/sql/security.sql new file mode 100644 index 0000000..7dfbbaa --- /dev/null +++ b/contrib/seg/sql/security.sql @@ -0,0 +1,32 @@ +-- +-- Test extension script protection against search path overriding +-- + +CREATE ROLE regress_seg_role; +SELECT current_database() AS datname \gset +GRANT CREATE ON DATABASE :"datname" TO regress_seg_role; +SET ROLE regress_seg_role; +CREATE SCHEMA regress_seg_schema; + +CREATE FUNCTION regress_seg_schema.exfun(i int) RETURNS int AS $$ +BEGIN + CREATE EXTENSION seg VERSION '1.2'; + + CREATE FUNCTION regress_seg_schema.compare(oid, regclass) RETURNS boolean AS + 'BEGIN RAISE EXCEPTION ''overloaded compare() called by %'', current_user; END;' LANGUAGE plpgsql; + + CREATE OPERATOR = (LEFTARG = oid, RIGHTARG = regclass, PROCEDURE = regress_seg_schema.compare); + + ALTER EXTENSION seg UPDATE TO '1.3'; + + RETURN i; +END; $$ LANGUAGE plpgsql; + +CREATE SCHEMA test_schema +CREATE TABLE t(i int) PARTITION BY RANGE (i) +CREATE TABLE p1 PARTITION OF t FOR VALUES FROM (1) TO (regress_seg_schema.exfun(2)); + +DROP SCHEMA test_schema CASCADE; +RESET ROLE; +DROP OWNED BY regress_seg_role; +DROP ROLE regress_seg_role; diff --git a/contrib/seg/sql/seg.sql b/contrib/seg/sql/seg.sql new file mode 100644 index 0000000..a027d4d --- /dev/null +++ b/contrib/seg/sql/seg.sql @@ -0,0 +1,240 @@ +-- +-- Test seg datatype +-- + +CREATE EXTENSION seg; + +-- Check whether any of our opclasses fail amvalidate +SELECT amname, opcname +FROM pg_opclass opc LEFT JOIN pg_am am ON am.oid = opcmethod +WHERE opc.oid >= 16384 AND NOT amvalidate(opc.oid); + +-- +-- testing the input and output functions +-- + +-- Any number +SELECT '1'::seg AS seg; +SELECT '-1'::seg AS seg; +SELECT '1.0'::seg AS seg; +SELECT '-1.0'::seg AS seg; +SELECT '1e7'::seg AS seg; +SELECT '-1e7'::seg AS seg; +SELECT '1.0e7'::seg AS seg; +SELECT '-1.0e7'::seg AS seg; +SELECT '1e+7'::seg AS seg; +SELECT '-1e+7'::seg AS seg; +SELECT '1.0e+7'::seg AS seg; +SELECT '-1.0e+7'::seg AS seg; +SELECT '1e-7'::seg AS seg; +SELECT '-1e-7'::seg AS seg; +SELECT '1.0e-7'::seg AS seg; +SELECT '-1.0e-7'::seg AS seg; +SELECT '2e-6'::seg AS seg; +SELECT '2e-5'::seg AS seg; +SELECT '2e-4'::seg AS seg; +SELECT '2e-3'::seg AS seg; +SELECT '2e-2'::seg AS seg; +SELECT '2e-1'::seg AS seg; +SELECT '2e-0'::seg AS seg; +SELECT '2e+0'::seg AS seg; +SELECT '2e+1'::seg AS seg; +SELECT '2e+2'::seg AS seg; +SELECT '2e+3'::seg AS seg; +SELECT '2e+4'::seg AS seg; +SELECT '2e+5'::seg AS seg; +SELECT '2e+6'::seg AS seg; + + +-- Significant digits preserved +SELECT '1'::seg AS seg; +SELECT '1.0'::seg AS seg; +SELECT '1.00'::seg AS seg; +SELECT '1.000'::seg AS seg; +SELECT '1.0000'::seg AS seg; +SELECT '1.00000'::seg AS seg; +SELECT '1.000000'::seg AS seg; +SELECT '0.000000120'::seg AS seg; +SELECT '3.400e5'::seg AS seg; + +-- Digits truncated +SELECT '12.34567890123456'::seg AS seg; + +-- Same, with a very long input +SELECT '12.3456789012345600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'::seg AS seg; + +-- Numbers with certainty indicators +SELECT '~6.5'::seg AS seg; +SELECT '<6.5'::seg AS seg; +SELECT '>6.5'::seg AS seg; +SELECT '~ 6.5'::seg AS seg; +SELECT '< 6.5'::seg AS seg; +SELECT '> 6.5'::seg AS seg; + +-- Open intervals +SELECT '0..'::seg AS seg; +SELECT '0...'::seg AS seg; +SELECT '0 ..'::seg AS seg; +SELECT '0 ...'::seg AS seg; +SELECT '..0'::seg AS seg; +SELECT '...0'::seg AS seg; +SELECT '.. 0'::seg AS seg; +SELECT '... 0'::seg AS seg; + +-- Finite intervals +SELECT '0 .. 1'::seg AS seg; +SELECT '-1 .. 0'::seg AS seg; +SELECT '-1 .. 1'::seg AS seg; + +-- (+/-) intervals +SELECT '0(+-)1'::seg AS seg; +SELECT '0(+-)1.0'::seg AS seg; +SELECT '1.0(+-)0.005'::seg AS seg; +SELECT '101(+-)1'::seg AS seg; +-- incorrect number of significant digits in 99.0: +SELECT '100(+-)1'::seg AS seg; + +-- invalid input +SELECT ''::seg AS seg; +SELECT 'ABC'::seg AS seg; +SELECT '1ABC'::seg AS seg; +SELECT '1.'::seg AS seg; +SELECT '1.....'::seg AS seg; +SELECT '.1'::seg AS seg; +SELECT '1..2.'::seg AS seg; +SELECT '1 e7'::seg AS seg; +SELECT '1e700'::seg AS seg; + +-- +-- testing the operators +-- + +-- equality/inequality: +-- +SELECT '24 .. 33.20'::seg = '24 .. 33.20'::seg AS bool; +SELECT '24 .. 33.20'::seg = '24 .. 33.21'::seg AS bool; +SELECT '24 .. 33.20'::seg != '24 .. 33.20'::seg AS bool; +SELECT '24 .. 33.20'::seg != '24 .. 33.21'::seg AS bool; + +-- overlap +-- +SELECT '1'::seg && '1'::seg AS bool; +SELECT '1'::seg && '2'::seg AS bool; +SELECT '0 ..'::seg && '0 ..'::seg AS bool; +SELECT '0 .. 1'::seg && '0 .. 1'::seg AS bool; +SELECT '..0'::seg && '0..'::seg AS bool; +SELECT '-1 .. 0.1'::seg && '0 .. 1'::seg AS bool; +SELECT '-1 .. 0'::seg && '0 .. 1'::seg AS bool; +SELECT '-1 .. -0.0001'::seg && '0 .. 1'::seg AS bool; +SELECT '0 ..'::seg && '1'::seg AS bool; +SELECT '0 .. 1'::seg && '1'::seg AS bool; +SELECT '0 .. 1'::seg && '2'::seg AS bool; +SELECT '0 .. 2'::seg && '1'::seg AS bool; +SELECT '1'::seg && '0 .. 1'::seg AS bool; +SELECT '2'::seg && '0 .. 1'::seg AS bool; +SELECT '1'::seg && '0 .. 2'::seg AS bool; + +-- overlap on the left +-- +SELECT '1'::seg &< '0'::seg AS bool; +SELECT '1'::seg &< '1'::seg AS bool; +SELECT '1'::seg &< '2'::seg AS bool; +SELECT '0 .. 1'::seg &< '0'::seg AS bool; +SELECT '0 .. 1'::seg &< '1'::seg AS bool; +SELECT '0 .. 1'::seg &< '2'::seg AS bool; +SELECT '0 .. 1'::seg &< '0 .. 0.5'::seg AS bool; +SELECT '0 .. 1'::seg &< '0 .. 1'::seg AS bool; +SELECT '0 .. 1'::seg &< '0 .. 2'::seg AS bool; +SELECT '0 .. 1'::seg &< '1 .. 2'::seg AS bool; +SELECT '0 .. 1'::seg &< '2 .. 3'::seg AS bool; + +-- overlap on the right +-- +SELECT '0'::seg &> '1'::seg AS bool; +SELECT '1'::seg &> '1'::seg AS bool; +SELECT '2'::seg &> '1'::seg AS bool; +SELECT '0'::seg &> '0 .. 1'::seg AS bool; +SELECT '1'::seg &> '0 .. 1'::seg AS bool; +SELECT '2'::seg &> '0 .. 1'::seg AS bool; +SELECT '0 .. 0.5'::seg &> '0 .. 1'::seg AS bool; +SELECT '0 .. 1'::seg &> '0 .. 1'::seg AS bool; +SELECT '0 .. 2'::seg &> '0 .. 2'::seg AS bool; +SELECT '1 .. 2'::seg &> '0 .. 1'::seg AS bool; +SELECT '2 .. 3'::seg &> '0 .. 1'::seg AS bool; + +-- left +-- +SELECT '1'::seg << '0'::seg AS bool; +SELECT '1'::seg << '1'::seg AS bool; +SELECT '1'::seg << '2'::seg AS bool; +SELECT '0 .. 1'::seg << '0'::seg AS bool; +SELECT '0 .. 1'::seg << '1'::seg AS bool; +SELECT '0 .. 1'::seg << '2'::seg AS bool; +SELECT '0 .. 1'::seg << '0 .. 0.5'::seg AS bool; +SELECT '0 .. 1'::seg << '0 .. 1'::seg AS bool; +SELECT '0 .. 1'::seg << '0 .. 2'::seg AS bool; +SELECT '0 .. 1'::seg << '1 .. 2'::seg AS bool; +SELECT '0 .. 1'::seg << '2 .. 3'::seg AS bool; + +-- right +-- +SELECT '0'::seg >> '1'::seg AS bool; +SELECT '1'::seg >> '1'::seg AS bool; +SELECT '2'::seg >> '1'::seg AS bool; +SELECT '0'::seg >> '0 .. 1'::seg AS bool; +SELECT '1'::seg >> '0 .. 1'::seg AS bool; +SELECT '2'::seg >> '0 .. 1'::seg AS bool; +SELECT '0 .. 0.5'::seg >> '0 .. 1'::seg AS bool; +SELECT '0 .. 1'::seg >> '0 .. 1'::seg AS bool; +SELECT '0 .. 2'::seg >> '0 .. 2'::seg AS bool; +SELECT '1 .. 2'::seg >> '0 .. 1'::seg AS bool; +SELECT '2 .. 3'::seg >> '0 .. 1'::seg AS bool; + + +-- "contained in" (the left value belongs within the interval specified in the right value): +-- +SELECT '0'::seg <@ '0'::seg AS bool; +SELECT '0'::seg <@ '0 ..'::seg AS bool; +SELECT '0'::seg <@ '.. 0'::seg AS bool; +SELECT '0'::seg <@ '-1 .. 1'::seg AS bool; +SELECT '0'::seg <@ '-1 .. 1'::seg AS bool; +SELECT '-1'::seg <@ '-1 .. 1'::seg AS bool; +SELECT '1'::seg <@ '-1 .. 1'::seg AS bool; +SELECT '-1 .. 1'::seg <@ '-1 .. 1'::seg AS bool; + +-- "contains" (the left value contains the interval specified in the right value): +-- +SELECT '0'::seg @> '0'::seg AS bool; +SELECT '0 .. '::seg <@ '0'::seg AS bool; +SELECT '.. 0'::seg <@ '0'::seg AS bool; +SELECT '-1 .. 1'::seg <@ '0'::seg AS bool; +SELECT '0'::seg <@ '-1 .. 1'::seg AS bool; +SELECT '-1'::seg <@ '-1 .. 1'::seg AS bool; +SELECT '1'::seg <@ '-1 .. 1'::seg AS bool; + +-- Load some example data and build the index +-- +CREATE TABLE test_seg (s seg); + +\copy test_seg from 'data/test_seg.data' + +CREATE INDEX test_seg_ix ON test_seg USING gist (s); + +SET enable_indexscan = false; +EXPLAIN (COSTS OFF) +SELECT count(*) FROM test_seg WHERE s @> '11..11.3'; +SELECT count(*) FROM test_seg WHERE s @> '11..11.3'; +RESET enable_indexscan; + +SET enable_bitmapscan = false; +EXPLAIN (COSTS OFF) +SELECT count(*) FROM test_seg WHERE s @> '11..11.3'; +SELECT count(*) FROM test_seg WHERE s @> '11..11.3'; +RESET enable_bitmapscan; + +-- Test sorting +SELECT * FROM test_seg WHERE s @> '11..11.3' GROUP BY s; + +-- Test functions +SELECT seg_lower(s), seg_center(s), seg_upper(s) +FROM test_seg WHERE s @> '11.2..11.3' OR s IS NULL ORDER BY s; |