Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit432b098

Browse files
authored
Merge pull request#6 from msdemlei/add-moc-casts
Add MOC vs. other geometries casts
2 parents3a7f241 +d2dc156 commit432b098

File tree

12 files changed

+1005
-10
lines changed

12 files changed

+1005
-10
lines changed

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@
88
regression.out
99
regression.diffs
1010
tags
11+
buildpod

‎HACKING‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
SQL definitions
2+
===============
3+
4+
Long version:
5+
<https://www.postgresql.org/docs/current/extend-extensions.html>.
6+
7+
If you're writing new features that require SQL support, pick some
8+
descriptive name; let's say my_new_op.
9+
10+
Put your new code into a file called pgs_my_new_op.sql.in. The .in
11+
extension here usually indicates "it's for copying stuff together";
12+
usally, not much processing is done on such files.
13+
14+
Then edit the Makefile. The PGS_SQL variable contains a list of the
15+
SQL files eventually copied together, without the .in. Add your new
16+
file there.
17+
18+
You will also need to create an upgrade file. In order to tell postgres
19+
to execute it, increase PGSPHERE_VERSION as appropriate. As a
20+
consequence, you will have to::
21+
22+
git mv pg_sphere--<old version>.sql.in pg_sphere--<new version>.sql.in
23+
24+
and also to update the version in pg_sphere.control.
25+
26+
Then create a make rule::
27+
28+
pg_sphere--<old version>--<new version>.sql: pgs_my_new_op.sql.in
29+
cat $^ > $@
30+
31+
(of course, this will extend to having multiple sql.in files).
32+
33+
Finally, add the target of that rule to the DATA_built variable.
34+
35+
36+
Regression tests
37+
================
38+
39+
Regressions tests are as per
40+
<https://www.postgresql.org/docs/current/extend-pgxs.html>.
41+
42+
In short, write queries executing your new features into a file
43+
sql/my_new_op.sql, and add "my_new_op" (without the extension or the
44+
directory name) to both REGRESS and TESTS in the Makefile.
45+
46+
Then touch expected/my_new_op.out, run make test. This will of course
47+
fail, because your tests hopefully will output something. But then you
48+
can pick out the diff from
49+
/var/lib/postgresql/pgsphere/regression.diffs, have another critical
50+
look at it and generatoe your .out file from it.

‎Makefile‎

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
PGSPHERE_VERSION = 1.2.0
1+
PGSPHERE_VERSION = 1.2.1
22

33
# the base dir name may be changed depending on git clone command
44
SRC_DIR =$(shell basename$(shell pwd))
@@ -17,18 +17,19 @@ DATA_built = $(RELEASE_SQL) \
1717
pg_sphere--1.0_gavo--1.1.5beta0gavo.sql\
1818
pg_sphere--1.1.5beta0gavo--1.1.5beta2gavo.sql\
1919
pg_sphere--1.1.5beta2gavo--1.1.5beta4gavo.sql\
20-
pg_sphere--1.1.5beta4gavo--1.2.0.sql
20+
pg_sphere--1.1.5beta4gavo--1.2.0.sql\
21+
pg_sphere--1.2.0--1.2.1.sql
2122

2223
DOCS = README.pg_sphere COPYRIGHT.pg_sphere
2324
REGRESS = init tables points euler circle line ellipse poly path box index\
2425
contains_ops contains_ops_compat bounding_box_gist gnomo healpix\
25-
moc
26+
moc mocautocast
2627

2728
REGRESS_9_5 = index_9.5# experimental for spoint3
2829

2930
TESTS = init_test tables points euler circle line ellipse poly path box index\
3031
contains_ops contains_ops_compat bounding_box_gist gnomo healpix\
31-
moc
32+
moc mocautocast
3233

3334
ifndefCXXFLAGS
3435
# no support for CXXFLAGS in PGXS before v11
@@ -45,7 +46,8 @@ PGS_SQL = pgs_types.sql pgs_point.sql pgs_euler.sql pgs_circle.sql \
4546
pgs_line.sql pgs_ellipse.sql pgs_polygon.sql pgs_path.sql\
4647
pgs_box.sql pgs_contains_ops.sql pgs_contains_ops_compat.sql\
4748
pgs_gist.sql gnomo.sql\
48-
healpix.sql pgs_gist_spoint3.sql pgs_moc_type.sql pgs_moc_compat.sql pgs_moc_ops.sql
49+
healpix.sql pgs_gist_spoint3.sql pgs_moc_type.sql pgs_moc_compat.sql pgs_moc_ops.sql\
50+
pgs_moc_geo_casts.sql
4951
PGS_SQL_9_5 = pgs_9.5.sql# experimental for spoint3
5052

5153
USE_PGXS = 1
@@ -155,7 +157,7 @@ ifeq ($(pg_version_9_5_plus),y)
155157
else
156158
endif
157159

158-
# local stuff follows here, next will be "beta2"
160+
# local stuff follows here
159161

160162
AUGMENT_GAVO_111 =$(AUGMENT_UNP_111) healpix.sql# for vanilla 1.1.1 users
161163
UPGRADE_GAVO_111 =$(UPGRADE_UNP_COMMON)
@@ -197,6 +199,12 @@ ifeq ($(has_parallel), n)
197199
sed -i -e '/PARALLEL/d' $@# version $(pg_version) does not have support for PARALLEL
198200
endif
199201

202+
pg_sphere--1.2.0--1.2.1.sql: pgs_moc_geo_casts.sql.in
203+
cat$^>$@
204+
ifeq ($(has_parallel), n)
205+
sed -i -e '/PARALLEL/d' $@# version $(pg_version) does not have support for PARALLEL
206+
endif
207+
200208
# end of local stuff
201209

202210
sscan.o : sparse.c

‎doc/functions.sgm‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,34 @@
638638
</programlisting>
639639
</example>
640640

641+
<funcsynopsis>
642+
<funcprototype>
643+
<funcdef><function>max_order</function></funcdef>
644+
<paramdef>smoc</paramdef>
645+
</funcprototype>
646+
</funcsynopsis>
647+
<para>
648+
Returns the maximal order of an smoc.
649+
</para>
650+
<para>
651+
The maximal order of a MOC can be higher than than the highest
652+
order appearing in the serialisation. For instance, in the example
653+
below the full-sky coverage given at order 6 means that no patch
654+
larger than about 1 degree is not covered. In the ASCII
655+
serialisation, give the maximum order with an with an empty cell
656+
list.
657+
</para>
658+
659+
<example>
660+
<title>Obtaining a MOC order</title>
661+
<programlisting>
662+
<![CDATA[SELECT max_order(smoc('0/0-11 6/')) as order;]]>
663+
<![CDATA[ order]]>
664+
<![CDATA[-----------]]>
665+
<![CDATA[ 6 ]]>
666+
</programlisting>
667+
</example>
668+
641669
</sect2>
642670

643671
</sect1>

‎doc/gen_moccast.py‎

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# A script to create the automatic casts for overlaps and intersects
2+
# between MOCs and spolys/scircles.
3+
#
4+
# This has originally been used to create pg_sphere--1.2.0--1.2.1.sql.
5+
# Before 1.2.1 is release, this can be fixed to improve that SQL.
6+
# After the 1.2.1 release, this is just documentation on how MOC
7+
# casts were generated that is perhaps just a bit more readable than
8+
# that bunch of SQL.
9+
10+
importdatetime
11+
importre
12+
importsys
13+
14+
15+
OVERLAP_DEFS= [
16+
# func_stem, operator, commutator
17+
('subset','<@','@>'),
18+
('not_subset','!<@','!@>'),
19+
('superset','@>','<@'),
20+
('not_superset','!@>','!<@'),
21+
]
22+
23+
INTERSECT_DEFS= [
24+
# func_stem, operator, commutator
25+
('intersect','&&','&&'),
26+
('not_intersect','!&&','!&&'),
27+
]
28+
29+
30+
GEO_TYPES= ["scircle","spoly"]
31+
32+
OP_DEFS=OVERLAP_DEFS
33+
34+
35+
classAccum:
36+
"""an accumulator for our output.
37+
"""
38+
def__init__(self):
39+
self.parts= []
40+
41+
@property
42+
defcontent(self):
43+
return"".join(self.parts)
44+
45+
defwrite(self,s):
46+
self.parts.append(s)
47+
48+
defwriteln(self,*strings):
49+
self.parts.append("\n".join(strings)+"\n")
50+
51+
defreplace_last(self,subs):
52+
"""replaces the last non-whitespace char with the string subs.
53+
"""
54+
forindex,partinenumerate(reversed(self.parts)):
55+
ifpart.strip():
56+
break
57+
else:
58+
# nothing to replace
59+
return
60+
61+
index=-1-index
62+
self.parts[index]=re.sub("[^\s](\s*)$",
63+
lambdamat:subs+mat.group(1),
64+
self.parts[index])
65+
66+
defintroduce_section(self,sec_name):
67+
self.writeln()
68+
self.writeln("-- #################################")
69+
self.writeln(f"--{sec_name}")
70+
71+
72+
defemit_drop_code(accum):
73+
accum.introduce_section("Cleanup")
74+
75+
accum.writeln("DROP OPERATOR IF EXISTS")
76+
for_,op,_inOP_DEFS:
77+
forgeo_typeinGEO_TYPES:
78+
accum.writeln(f"{op} (smoc,{geo_type}),")
79+
accum.writeln(f"{op} ({geo_type}, smoc),")
80+
accum.replace_last(";")
81+
82+
83+
defmake_negator(op):
84+
ifop.startswith("!"):
85+
returnop[1:]
86+
else:
87+
return"!"+op
88+
89+
90+
defemit_op_def(accum,operator,leftarg,rightarg,procedure,commutator):
91+
accum.writeln(
92+
f"CREATE OPERATOR{operator} (",
93+
f" LEFTARG ={leftarg},",
94+
f" RIGHTARG ={rightarg},",
95+
f" PROCEDURE ={procedure},",
96+
f" COMMUTATOR = '{commutator}',",
97+
f" NEGATOR = '{make_negator(operator)}',",
98+
f" RESTRICT = contsel,",
99+
f" JOIN = contjoinsel",
100+
f");")
101+
102+
103+
defemit_op_and_func(accum,op_def):
104+
func_stem,operator,commutator=op_def
105+
forgeo_typeinGEO_TYPES:
106+
func_name=f"{geo_type}_{func_stem}_smoc"
107+
accum.writeln(
108+
f"CREATE OR REPLACE FUNCTION{func_name}(",
109+
f" geo_arg{geo_type}, a_moc smoc) RETURNS BOOL AS $body$",
110+
f" SELECT smoc(max_order(a_moc), geo_arg){operator} a_moc",
111+
f" $body$ LANGUAGE SQL STABLE;")
112+
emit_op_def(accum,operator,
113+
geo_type,"smoc",
114+
func_name,
115+
commutator)
116+
117+
accum.writeln()
118+
119+
func_name=f"smoc_{func_stem}_{geo_type}"
120+
accum.writeln(
121+
f"CREATE OR REPLACE FUNCTION{func_name}(",
122+
f" a_moc smoc, geo_arg{geo_type}) RETURNS BOOL AS $body$",
123+
f" SELECT a_moc{operator} smoc(max_order(a_moc), geo_arg)",
124+
f" $body$ LANGUAGE SQL STABLE;")
125+
emit_op_def(accum,operator,
126+
"smoc",geo_type,
127+
func_name,
128+
commutator)
129+
130+
accum.writeln()
131+
132+
133+
defmain():
134+
accum=Accum()
135+
136+
accum.writeln("-- MOC/geometry automatic casts.")
137+
accum.writeln(f"-- Generated{datetime.date.today()} by{sys.argv[0]}.")
138+
accum.writeln(f"-- Re-generation needs to be triggered manually.")
139+
accum.writeln()
140+
emit_drop_code(accum)
141+
142+
accum.introduce_section(" smoc/geo OVERLAPS")
143+
forop_definOVERLAP_DEFS:
144+
emit_op_and_func(accum,op_def)
145+
accum.writeln()
146+
147+
accum.introduce_section(" smoc/geo INTERSECTS")
148+
forop_definINTERSECT_DEFS:
149+
emit_op_and_func(accum,op_def)
150+
accum.writeln()
151+
152+
print(accum.content)
153+
154+
155+
if__name__=="__main__":
156+
main()

‎doc/operators.sgm‎

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,10 +231,19 @@
231231
<para>
232232
An overlap or contain operator does not exist for all
233233
combinations of data types.
234-
For instance, scircle<@ <type>spoint</type> is
234+
For instance, scircle&lt;@ <type>spoint</type> is
235235
useless because a spherical point can never contain a
236236
spherical circle.
237237
</para>
238+
<para>
239+
When one of the arguments of such an operator is a MOC
240+
and the other is an scircle or an spoly, the non-MOC argument
241+
is converted to a MOC of the order of the maximum order of
242+
the MOC. When comparing against a MOC-valued column, it
243+
is usually much faster to explicitly convert the geometry
244+
using the smoc constructor, as the conversion will then
245+
only happen once.
246+
</para>
238247
<example>
239248
<title>Is the left circle contained by the right circle?</title>
240249
<programlisting>
@@ -255,6 +264,40 @@
255264
<![CDATA[(1 row)]]>
256265
</programlisting>
257266
</example>
267+
268+
<example>
269+
<title>Overlaps between a circle and a moc</title>
270+
<programlisting>
271+
<![CDATA[sql> SELECT scircle '<(37d, 5d), 0.25d>' <@ smoc('4/1117') AS test ;]]>
272+
<![CDATA[ test]]>
273+
<![CDATA[------]]>
274+
<![CDATA[ f]]>
275+
<![CDATA[(1 row)]]>
276+
</programlisting>
277+
</example>
278+
279+
<example>
280+
<title>Overlaps between a circle and a moc with explicit order</title>
281+
<programlisting>
282+
<![CDATA[sql> SELECT scircle '<(37d, 5d), 0.25d>' <@ smoc('4/1117 5/') AS test ;]]>
283+
<![CDATA[ test]]>
284+
<![CDATA[------]]>
285+
<![CDATA[ t]]>
286+
<![CDATA[(1 row)]]>
287+
</programlisting>
288+
</example>
289+
290+
<example>
291+
<title>Overlaps between a circle and a moc with explicit cast (normally faster)</title>
292+
<programlisting>
293+
<![CDATA[sql> SELECT smoc(5, scircle '<(37d, 5d), 0.25d>') <@ smoc('4/1117 5/') AS test ;]]>
294+
<![CDATA[ test]]>
295+
<![CDATA[------]]>
296+
<![CDATA[ t]]>
297+
<![CDATA[(1 row)]]>
298+
</programlisting>
299+
</example>
300+
258301
</sect2>
259302

260303
<sect2 id="op.cross">

‎expected/init_test.out‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,5 @@ psql:pg_sphere.test.sql:8569: NOTICE: argument type pointkey is only a shell
3333
psql:pg_sphere.test.sql:8575: NOTICE: argument type pointkey is only a shell
3434
psql:pg_sphere.test.sql:8581: NOTICE: argument type pointkey is only a shell
3535
psql:pg_sphere.test.sql:8587: NOTICE: argument type pointkey is only a shell
36-
psql:pg_sphere.test.sql:9152: NOTICE: return type smoc is only a shell
37-
psql:pg_sphere.test.sql:9158: NOTICE: argument type smoc is only a shell
36+
psql:pg_sphere.test.sql:9154: NOTICE: return type smoc is only a shell
37+
psql:pg_sphere.test.sql:9160: NOTICE: argument type smoc is only a shell

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp