[PATCH] Revive line type
Hi,
Test results are as follows:
Contents & Purpose
This patch is for finishing the line type and related functions that not
done yet but listed in catalogs and documentation. There are no other new
features added in this patch.
The regression test cases which included in this patch, Documentation are
also updated.
Run
Regression tests are all succeed, but several problems have be found while
ding some simple test. The updated document said that the points used in
the output are not necessarily the points used on input. I understand that
as long as they are marked on the same line. But when the input data
represents a horizontal or vertical line, the output is not exactly the
same line. It is another line parallel to it.
For example:
postgres=# select line('1,3,2,3');
line
-----------------
[(0,-3),(1,-3)]
(1 row)
postgres=# select line('1,3,1,6');
line
-----------------
[(-1,0),(-1,1)]
(1 row)
In addition, when a straight line coincides with coordinate axis, output
appears -0, I do not know whether it is appropriate.
postgres=# select line('0,1,0,5');
line
-----------------
[(-0,0),(-0,1)]
(1 row)
Negative value appeared when use <-> to calculate the distance between two
parallel lines.
postgres=# select line('1,1,2,1') <-> line('-1,-1,-2,-1') ;
?column?
----------
-2
postgres=# select lseg('1,1,2,1') <-> line('-1,-1,-2,-1') ;
?column?
----------
-2
(1 row)
The same situation occurs in distance calculation between point and a
straight line.
postgres=# select point('-1,1') <-> line('-3,0,-4,0') ;
?column?
----------
-1
(1 row)
Should the distance be positive numbers?
Other functions seem work properly.
Performance
==================================
Because these functions is first implemented. So there is no relatively
comparison for the performance.
Conclusion
This patch lets line type worked. But there are some bugs. Additionally,
function "close_sl" not implemented.
With Regards,
Rui
On Sun, 2013-06-23 at 12:24 +0800, rui hua wrote:
Regression tests are all succeed, but several problems have be found while
ding some simple test. The updated document said that the points used in
the output are not necessarily the points used on input. I understand that
as long as they are marked on the same line. But when the input data
represents a horizontal or vertical line, the output is not exactly the
same line. It is another line parallel to it.
postgres=# select line('1,3,2,3');
line
-----------------
[(0,-3),(1,-3)]
(1 row)
This was just using the wrong sign. Fixed.
In addition, when a straight line coincides with coordinate axis, output
appears -0, I do not know whether it is appropriate.
This is a matter of the floating-point operations. I don't think it's
on scope to worry about that. With the above fix, the cases you pointed
out go away anyway.
Negative value appeared when use <-> to calculate the distance between two
parallel lines.
Fixed with fabs().
New patch included. Still wondering whether to use a A,B,C-based output
format per Tom's comment.
Attachments:
0001-Revive-line-type.patchtext/x-patch; charset=UTF-8; name=0001-Revive-line-type.patchDownload
>From d765f8a515a6f3de0e68e68962e5109945260b8c Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter_e@gmx.net>
Date: Fri, 14 Jun 2013 20:23:15 -0400
Subject: [PATCH] Revive line type
Complete the implementations of line_in, line_out, line_recv,
line_send. Remove comments and error messages about the line type not
being implemented. Add regression tests for existing line operators
and functions.
Reviewed-by: rui hua <365507506hua@gmail.com>
---
doc/src/sgml/datatype.sgml | 34 +++-
doc/src/sgml/func.sgml | 6 +
src/backend/utils/adt/geo_ops.c | 112 +++++-------
src/include/catalog/pg_type.h | 3 +-
src/include/utils/geo_decls.h | 7 -
src/test/regress/expected/geometry.out | 3 -
src/test/regress/expected/line.out | 267 ++++++++++++++++++++++++++++
src/test/regress/expected/sanity_check.out | 3 +-
src/test/regress/output/misc.source | 3 +-
src/test/regress/parallel_schedule | 2 +-
src/test/regress/serial_schedule | 1 +
src/test/regress/sql/geometry.sql | 4 -
src/test/regress/sql/line.sql | 86 +++++++++
13 files changed, 443 insertions(+), 88 deletions(-)
create mode 100644 src/test/regress/expected/line.out
create mode 100644 src/test/regress/sql/line.sql
diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index f73e6b2..ecbbdd8 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -3066,7 +3066,7 @@ <title>Geometric Types</title>
<row>
<entry><type>line</type></entry>
<entry>32 bytes</entry>
- <entry>Infinite line (not fully implemented)</entry>
+ <entry>Infinite line</entry>
<entry>((x1,y1),(x2,y2))</entry>
</row>
<row>
@@ -3142,6 +3142,38 @@ <title>Points</title>
</sect2>
<sect2>
+ <title>Lines</title>
+
+ <indexterm>
+ <primary>line</primary>
+ </indexterm>
+
+ <para>
+ Lines (<type>line</type>) are specified by pairs of points.
+ Values of type <type>line</type> are specified using any of the following
+ syntaxes:
+
+<synopsis>
+[ ( <replaceable>x1</replaceable> , <replaceable>y1</replaceable> ) , ( <replaceable>x2</replaceable> , <replaceable>y2</replaceable> ) ]
+( ( <replaceable>x1</replaceable> , <replaceable>y1</replaceable> ) , ( <replaceable>x2</replaceable> , <replaceable>y2</replaceable> ) )
+ ( <replaceable>x1</replaceable> , <replaceable>y1</replaceable> ) , ( <replaceable>x2</replaceable> , <replaceable>y2</replaceable> )
+ <replaceable>x1</replaceable> , <replaceable>y1</replaceable> , <replaceable>x2</replaceable> , <replaceable>y2</replaceable>
+</synopsis>
+
+ where
+ <literal>(<replaceable>x1</replaceable>,<replaceable>y1</replaceable>)</literal>
+ and
+ <literal>(<replaceable>x2</replaceable>,<replaceable>y2</replaceable>)</literal>
+ are two (different) points on the line.
+ </para>
+
+ <para>
+ Lines are output using the first syntax. The points used in the output
+ are not necessarily the points used on input.
+ </para>
+ </sect2>
+
+ <sect2>
<title>Line Segments</title>
<indexterm>
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 8cf5385..fd0e4a3 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -8070,6 +8070,12 @@ <title>Geometric Type Conversion Functions</title>
<entry><literal>circle(polygon '((0,0),(1,1),(2,0))')</literal></entry>
</row>
<row>
+ <entry><literal><function>line(<type>point</type>, <type>point</type>)</function></literal></entry>
+ <entry><type>line</type></entry>
+ <entry>points to line</entry>
+ <entry><literal>lseg(point '(-1,0)', point '(1,0)')</literal></entry>
+ </row>
+ <row>
<entry>
<indexterm>
<primary>lseg</primary>
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index ad18cf0..e668a21 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -933,13 +933,8 @@
Datum
line_in(PG_FUNCTION_ARGS)
{
-#ifdef ENABLE_LINE_TYPE
char *str = PG_GETARG_CSTRING(0);
-#endif
LINE *line;
-
-#ifdef ENABLE_LINE_TYPE
- /* when fixed, modify "not implemented", catalog/pg_type.h and SGML */
LSEG lseg;
int isopen;
char *s;
@@ -950,15 +945,13 @@
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type line: \"%s\"", str)));
+ if (FPeq(lseg.p[0].x, lseg.p[1].x) && FPeq(lseg.p[0].y, lseg.p[1].y))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid line specification: must be two distinct points")));
+
line = (LINE *) palloc(sizeof(LINE));
line_construct_pts(line, &lseg.p[0], &lseg.p[1]);
-#else
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("type \"line\" not yet implemented")));
-
- line = NULL;
-#endif
PG_RETURN_LINE_P(line);
}
@@ -967,66 +960,31 @@
Datum
line_out(PG_FUNCTION_ARGS)
{
-#ifdef ENABLE_LINE_TYPE
LINE *line = PG_GETARG_LINE_P(0);
-#endif
- char *result;
-
-#ifdef ENABLE_LINE_TYPE
- /* when fixed, modify "not implemented", catalog/pg_type.h and SGML */
LSEG lseg;
if (FPzero(line->B))
{ /* vertical */
/* use "x = C" */
- result->A = -1;
- result->B = 0;
- result->C = pt1->x;
-#ifdef GEODEBUG
- printf("line_out- line is vertical\n");
-#endif
-#ifdef NOT_USED
- result->m = DBL_MAX;
-#endif
-
+ lseg.p[0].x = lseg.p[1].x = - line->C/line->A;
+ lseg.p[0].y = 0;
+ lseg.p[1].y = 1;
}
else if (FPzero(line->A))
{ /* horizontal */
- /* use "x = C" */
- result->A = 0;
- result->B = -1;
- result->C = pt1->y;
-#ifdef GEODEBUG
- printf("line_out- line is horizontal\n");
-#endif
-#ifdef NOT_USED
- result->m = 0.0;
-#endif
-
+ lseg.p[0].x = 0;
+ lseg.p[1].x = 1;
+ lseg.p[0].y = lseg.p[1].y = - line->C/line->B;
}
else
{
+ lseg.p[0].x = 0;
+ lseg.p[0].y = - line->C/line->B;
+ lseg.p[1].x = 1;
+ lseg.p[1].y = (-line->C - line->A)/line->B;
}
- if (FPzero(line->A)) /* horizontal? */
- {
- }
- else if (FPzero(line->B)) /* vertical? */
- {
- }
- else
- {
- }
-
- return path_encode(TRUE, 2, (Point *) &(ls->p[0]));
-#else
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("type \"line\" not yet implemented")));
- result = NULL;
-#endif
-
- PG_RETURN_CSTRING(result);
+ PG_RETURN_CSTRING(path_encode(FALSE, 2, (Point *) &(lseg.p[0])));
}
/*
@@ -1035,10 +993,16 @@
Datum
line_recv(PG_FUNCTION_ARGS)
{
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("type \"line\" not yet implemented")));
- return 0;
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ LINE *line;
+
+ line = (LINE *) palloc(sizeof(LINE));
+
+ line->A = pq_getmsgfloat8(buf);
+ line->B = pq_getmsgfloat8(buf);
+ line->C = pq_getmsgfloat8(buf);
+
+ PG_RETURN_LINE_P(line);
}
/*
@@ -1047,10 +1011,14 @@
Datum
line_send(PG_FUNCTION_ARGS)
{
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("type \"line\" not yet implemented")));
- return 0;
+ LINE *line = PG_GETARG_LINE_P(0);
+ StringInfoData buf;
+
+ pq_begintypsend(&buf);
+ pq_sendfloat8(&buf, line->A);
+ pq_sendfloat8(&buf, line->B);
+ pq_sendfloat8(&buf, line->C);
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
@@ -2447,8 +2415,8 @@
static double
dist_pl_internal(Point *pt, LINE *line)
{
- return (line->A * pt->x + line->B * pt->y + line->C) /
- HYPOT(line->A, line->B);
+ return fabs((line->A * pt->x + line->B * pt->y + line->C) /
+ HYPOT(line->A, line->B));
}
Datum
@@ -3036,6 +3004,7 @@
Datum
close_sl(PG_FUNCTION_ARGS)
{
+#ifdef NOT_USED
LSEG *lseg = PG_GETARG_LSEG_P(0);
LINE *line = PG_GETARG_LINE_P(1);
Point *result;
@@ -3054,6 +3023,13 @@
result = point_copy(&lseg->p[1]);
PG_RETURN_POINT_P(result);
+#endif
+
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("function \"close_sl\" not implemented")));
+
+ PG_RETURN_NULL();
}
/* close_ls()
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index e3822fa..2081312 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -393,10 +393,9 @@ DESCR("geometric polygon '(pt1,...)'");
#define POLYGONOID 604
DATA(insert OID = 628 ( line PGNSP PGUID 32 f b G f t \054 0 701 629 line_in line_out line_recv line_send - - - d p f 0 -1 0 0 _null_ _null_ _null_ ));
-DESCR("geometric line (not implemented)");
+DESCR("geometric line");
#define LINEOID 628
DATA(insert OID = 629 ( _line PGNSP PGUID -1 f b A f t \054 0 628 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DESCR("");
/* OIDS 700 - 799 */
diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h
index 5c83a71..1e648c0 100644
--- a/src/include/utils/geo_decls.h
+++ b/src/include/utils/geo_decls.h
@@ -88,19 +88,12 @@ typedef struct
/*---------------------------------------------------------------------
* LINE - Specified by its general equation (Ax+By+C=0).
- * If there is a y-intercept, it is C, which
- * incidentally gives a freebie point on the line
- * (if B=0, then C is the x-intercept).
- * Slope m is precalculated to save time; if
- * the line is not vertical, m == A.
*-------------------------------------------------------------------*/
typedef struct
{
double A,
B,
C;
-
- double m;
} LINE;
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index 8123725..21ad555 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -146,9 +146,6 @@ SELECT '' AS thirty, p.f1, l.s, p.f1 ## l.s AS closest
(30 rows)
--
--- Lines
---
---
-- Boxes
--
SELECT '' as six, box(f1) AS box FROM CIRCLE_TBL;
diff --git a/src/test/regress/expected/line.out b/src/test/regress/expected/line.out
new file mode 100644
index 0000000..0ef992d
--- /dev/null
+++ b/src/test/regress/expected/line.out
@@ -0,0 +1,267 @@
+--
+-- LINE
+-- Infinite lines
+--
+--DROP TABLE LINE_TBL;
+CREATE TABLE LINE_TBL (s line);
+INSERT INTO LINE_TBL VALUES ('[(1,2),(3,4)]');
+INSERT INTO LINE_TBL VALUES ('(0,0),(6,6)');
+INSERT INTO LINE_TBL VALUES ('10,-10 ,-3,-4');
+INSERT INTO LINE_TBL VALUES ('[-1e6,2e2,3e5, -4e1]');
+INSERT INTO LINE_TBL VALUES ('(11,22,33,44)');
+INSERT INTO LINE_TBL VALUES ('[(1,0),(1,0)]');
+ERROR: invalid line specification: must be two distinct points
+LINE 1: INSERT INTO LINE_TBL VALUES ('[(1,0),(1,0)]');
+ ^
+-- horizontal
+INSERT INTO LINE_TBL VALUES ('[(1,3),(2,3)]');
+-- vertical
+INSERT INTO LINE_TBL VALUES ('[(3,1),(3,2)]');
+-- bad values for parser testing
+INSERT INTO LINE_TBL VALUES ('(3asdf,2 ,3,4r2)');
+ERROR: invalid input syntax for type line: "(3asdf,2 ,3,4r2)"
+LINE 1: INSERT INTO LINE_TBL VALUES ('(3asdf,2 ,3,4r2)');
+ ^
+INSERT INTO LINE_TBL VALUES ('[1,2,3, 4');
+ERROR: invalid input syntax for type line: "[1,2,3, 4"
+LINE 1: INSERT INTO LINE_TBL VALUES ('[1,2,3, 4');
+ ^
+INSERT INTO LINE_TBL VALUES ('[(,2),(3,4)]');
+ERROR: invalid input syntax for type line: "[(,2),(3,4)]"
+LINE 1: INSERT INTO LINE_TBL VALUES ('[(,2),(3,4)]');
+ ^
+INSERT INTO LINE_TBL VALUES ('[(1,2),(3,4)');
+ERROR: invalid input syntax for type line: "[(1,2),(3,4)"
+LINE 1: INSERT INTO LINE_TBL VALUES ('[(1,2),(3,4)');
+ ^
+select * from LINE_TBL;
+ s
+-----------------------------------------------
+ [(0,1),(1,2)]
+ [(0,0),(1,1)]
+ [(0,-5.38461538461538),(1,-5.84615384615385)]
+ [(0,15.3846153846154),(1,15.3844307692308)]
+ [(0,11),(1,12)]
+ [(0,3),(1,3)]
+ [(3,0),(3,1)]
+(7 rows)
+
+-- functions and operators
+SELECT * FROM LINE_TBL WHERE (s <-> line '[(1,2),(3,4)]') < 10;
+ s
+-----------------------------------------------
+ [(0,1),(1,2)]
+ [(0,0),(1,1)]
+ [(0,-5.38461538461538),(1,-5.84615384615385)]
+ [(0,15.3846153846154),(1,15.3844307692308)]
+ [(0,11),(1,12)]
+ [(0,3),(1,3)]
+ [(3,0),(3,1)]
+(7 rows)
+
+SELECT * FROM LINE_TBL WHERE (point '(0.1,0.1)' <-> s) < 1;
+ s
+---------------
+ [(0,1),(1,2)]
+ [(0,0),(1,1)]
+(2 rows)
+
+SELECT * FROM LINE_TBL WHERE (lseg '[(0.1,0.1),(0.2,0.2)]' <-> s) < 1;
+ s
+---------------
+ [(0,1),(1,2)]
+ [(0,0),(1,1)]
+(2 rows)
+
+SELECT line '[(1,1),(2,1)]' <-> line '[(-1,-1),(-2,-1)]';
+ ?column?
+----------
+ 2
+(1 row)
+
+SELECT lseg '[(1,1),(2,1)]' <-> line '[(-1,-1),(-2,-1)]';
+ ?column?
+----------
+ 2
+(1 row)
+
+SELECT point '(-1,1)' <-> line '[(-3,0),(-4,0)]';
+ ?column?
+----------
+ 1
+(1 row)
+
+SELECT lseg '[(1,1),(5,5)]' ?# line '[(2,0),(0,2)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT lseg '[(1,1),(5,5)]' ?# line '[(0,0),(1,0)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ?# box '(0,0,2,2)'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT line '[(3,0),(4,1)]' ?# box '(0,0,2,2)'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT point '(1,1)' <@ line '[(0,0),(2,2)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT point '(1,1)' <@ line '[(0,0),(1,0)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT point '(1,1)' @ line '[(0,0),(2,2)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT point '(1,1)' @ line '[(0,0),(1,0)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT lseg '[(1,1),(2,2)]' <@ line '[(0,0),(2,2)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT lseg '[(1,1),(2,1)]' <@ line '[(0,0),(1,0)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT lseg '[(1,1),(2,2)]' @ line '[(0,0),(2,2)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT lseg '[(1,1),(2,1)]' @ line '[(0,0),(1,0)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT point '(0,1)' ## line '[(0,0),(1,1)]';
+ ?column?
+-----------
+ (0.5,0.5)
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ## lseg '[(1,0),(2,0)]';
+ ?column?
+----------
+ (1,0)
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ?# line '[(1,0),(2,1)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ?# line '[(1,0),(1,1)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' # line '[(1,0),(2,1)]';
+ ?column?
+----------
+
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' # line '[(1,0),(1,1)]';
+ ?column?
+----------
+ (1,1)
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ?|| line '[(1,0),(2,1)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ?|| line '[(1,0),(1,1)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT line '[(0,0),(1,0)]' ?-| line '[(0,0),(0,1)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ?-| line '[(1,0),(1,1)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT ?- line '[(0,0),(1,0)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT ?- line '[(0,0),(1,1)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT ?| line '[(0,0),(0,1)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT ?| line '[(0,0),(1,1)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT line(point '(1,2)', point '(3,4)');
+ line
+---------------
+ [(0,1),(1,2)]
+(1 row)
+
+SELECT line '[(1,2),(3,4)]' = line '[(3,4),(4,5)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT line '[(1,2),(3,4)]' = line '[(3,4),(4,4)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index 432d39a..cee35af 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -64,6 +64,7 @@ SELECT relname, relhasindex
interval_tbl | f
iportaltest | f
kd_point_tbl | t
+ line_tbl | f
log_table | f
lseg_tbl | f
main_table | f
@@ -166,7 +167,7 @@ SELECT relname, relhasindex
timetz_tbl | f
tinterval_tbl | f
varchar_tbl | f
-(155 rows)
+(156 rows)
--
-- another sanity check: every system catalog that has OIDs should have
diff --git a/src/test/regress/output/misc.source b/src/test/regress/output/misc.source
index 29cbb22..e194f7e 100644
--- a/src/test/regress/output/misc.source
+++ b/src/test/regress/output/misc.source
@@ -638,6 +638,7 @@ SELECT user_relns() AS user_relns
interval_tbl
iportaltest
kd_point_tbl
+ line_tbl
log_table
lseg_tbl
main_table
@@ -696,7 +697,7 @@ SELECT user_relns() AS user_relns
tvvmv
varchar_tbl
xacttest
-(118 rows)
+(119 rows)
SELECT name(equipment(hobby_construct(text 'skywalking', text 'mer')));
name
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 2af28b1..cbedeb5 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -23,7 +23,7 @@ test: numerology
# ----------
# The second group of parallel tests
# ----------
-test: point lseg box path polygon circle date time timetz timestamp timestamptz interval abstime reltime tinterval inet macaddr tstypes comments
+test: point lseg line box path polygon circle date time timetz timestamp timestamptz interval abstime reltime tinterval inet macaddr tstypes comments
# ----------
# Another group of parallel tests
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index d6eaa7a..5b86ede 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -23,6 +23,7 @@ test: strings
test: numerology
test: point
test: lseg
+test: line
test: box
test: path
test: polygon
diff --git a/src/test/regress/sql/geometry.sql b/src/test/regress/sql/geometry.sql
index 73f8032..af7f8a5 100644
--- a/src/test/regress/sql/geometry.sql
+++ b/src/test/regress/sql/geometry.sql
@@ -59,10 +59,6 @@
FROM LSEG_TBL l, POINT_TBL p;
--
--- Lines
---
-
---
-- Boxes
--
diff --git a/src/test/regress/sql/line.sql b/src/test/regress/sql/line.sql
new file mode 100644
index 0000000..b24f730
--- /dev/null
+++ b/src/test/regress/sql/line.sql
@@ -0,0 +1,86 @@
+--
+-- LINE
+-- Infinite lines
+--
+
+--DROP TABLE LINE_TBL;
+CREATE TABLE LINE_TBL (s line);
+
+INSERT INTO LINE_TBL VALUES ('[(1,2),(3,4)]');
+INSERT INTO LINE_TBL VALUES ('(0,0),(6,6)');
+INSERT INTO LINE_TBL VALUES ('10,-10 ,-3,-4');
+INSERT INTO LINE_TBL VALUES ('[-1e6,2e2,3e5, -4e1]');
+INSERT INTO LINE_TBL VALUES ('(11,22,33,44)');
+
+INSERT INTO LINE_TBL VALUES ('[(1,0),(1,0)]');
+
+-- horizontal
+INSERT INTO LINE_TBL VALUES ('[(1,3),(2,3)]');
+-- vertical
+INSERT INTO LINE_TBL VALUES ('[(3,1),(3,2)]');
+
+-- bad values for parser testing
+INSERT INTO LINE_TBL VALUES ('(3asdf,2 ,3,4r2)');
+INSERT INTO LINE_TBL VALUES ('[1,2,3, 4');
+INSERT INTO LINE_TBL VALUES ('[(,2),(3,4)]');
+INSERT INTO LINE_TBL VALUES ('[(1,2),(3,4)');
+
+select * from LINE_TBL;
+
+
+-- functions and operators
+
+SELECT * FROM LINE_TBL WHERE (s <-> line '[(1,2),(3,4)]') < 10;
+
+SELECT * FROM LINE_TBL WHERE (point '(0.1,0.1)' <-> s) < 1;
+
+SELECT * FROM LINE_TBL WHERE (lseg '[(0.1,0.1),(0.2,0.2)]' <-> s) < 1;
+
+SELECT line '[(1,1),(2,1)]' <-> line '[(-1,-1),(-2,-1)]';
+SELECT lseg '[(1,1),(2,1)]' <-> line '[(-1,-1),(-2,-1)]';
+SELECT point '(-1,1)' <-> line '[(-3,0),(-4,0)]';
+
+SELECT lseg '[(1,1),(5,5)]' ?# line '[(2,0),(0,2)]'; -- true
+SELECT lseg '[(1,1),(5,5)]' ?# line '[(0,0),(1,0)]'; -- false
+
+SELECT line '[(0,0),(1,1)]' ?# box '(0,0,2,2)'; -- true
+SELECT line '[(3,0),(4,1)]' ?# box '(0,0,2,2)'; -- false
+
+SELECT point '(1,1)' <@ line '[(0,0),(2,2)]'; -- true
+SELECT point '(1,1)' <@ line '[(0,0),(1,0)]'; -- false
+
+SELECT point '(1,1)' @ line '[(0,0),(2,2)]'; -- true
+SELECT point '(1,1)' @ line '[(0,0),(1,0)]'; -- false
+
+SELECT lseg '[(1,1),(2,2)]' <@ line '[(0,0),(2,2)]'; -- true
+SELECT lseg '[(1,1),(2,1)]' <@ line '[(0,0),(1,0)]'; -- false
+
+SELECT lseg '[(1,1),(2,2)]' @ line '[(0,0),(2,2)]'; -- true
+SELECT lseg '[(1,1),(2,1)]' @ line '[(0,0),(1,0)]'; -- false
+
+SELECT point '(0,1)' ## line '[(0,0),(1,1)]';
+
+SELECT line '[(0,0),(1,1)]' ## lseg '[(1,0),(2,0)]';
+
+SELECT line '[(0,0),(1,1)]' ?# line '[(1,0),(2,1)]'; -- false
+SELECT line '[(0,0),(1,1)]' ?# line '[(1,0),(1,1)]'; -- true
+
+SELECT line '[(0,0),(1,1)]' # line '[(1,0),(2,1)]';
+SELECT line '[(0,0),(1,1)]' # line '[(1,0),(1,1)]';
+
+SELECT line '[(0,0),(1,1)]' ?|| line '[(1,0),(2,1)]'; -- true
+SELECT line '[(0,0),(1,1)]' ?|| line '[(1,0),(1,1)]'; -- false
+
+SELECT line '[(0,0),(1,0)]' ?-| line '[(0,0),(0,1)]'; -- true
+SELECT line '[(0,0),(1,1)]' ?-| line '[(1,0),(1,1)]'; -- false
+
+SELECT ?- line '[(0,0),(1,0)]'; -- true
+SELECT ?- line '[(0,0),(1,1)]'; -- false
+
+SELECT ?| line '[(0,0),(0,1)]'; -- true
+SELECT ?| line '[(0,0),(1,1)]'; -- false
+
+SELECT line(point '(1,2)', point '(3,4)');
+
+SELECT line '[(1,2),(3,4)]' = line '[(3,4),(4,5)]'; -- true
+SELECT line '[(1,2),(3,4)]' = line '[(3,4),(4,4)]'; -- false
--
1.7.10.4
On 6/26/13 9:34 PM, Peter Eisentraut wrote:
Still wondering whether to use a A,B,C-based output
format per Tom's comment.
Wouldn't it also be helpful to remove "The points used in the output are
not necessarily the points used on input" by making that not true?
There are three obvious ways you might output a line:
-Math class expectations of slope-intercept form: y = mx + b.
Intercept forms don't handle both horizontal and vertical lines though,
so that's easily out.
-Pair of points. A casual observer might get lucky and observe putting
a pair of points in and getting the same pair back again, then
incorrectly assume that's normally the case. Seems better to never make
that possible in the infinite line case. I'm reminded of how row output
usually is in order gives a bad impression about ordering guarantees in SQL.
-Ax+By+C=0
Outputting that third one, when it's also the internal form, handles any
time of line; will show any assumptions about individual points being
preserved are wrong; and avoids rounding errors too. The only downside
seems to be that bounded lines are easier to show with a pair of points.
I think that suggests an alternate, secondary output format would be
useful though, rather than that a different default one is a good idea.
--
Greg Smith 2ndQuadrant US greg@2ndQuadrant.com Baltimore, MD
PostgreSQL Training, Services, and 24x7 Support www.2ndQuadrant.com
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
Here is a new patch for the line type, with a new input/output format
{A,B,C}, as discussed in this thread.
Attachments:
0001-Revive-line-type.patchtext/x-patch; charset=UTF-8; name=0001-Revive-line-type.patchDownload
>From 837fcf5d9b1ee8e589ef4b19f7d6e575229ca758 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter_e@gmx.net>
Date: Sun, 15 Sep 2013 00:02:06 -0400
Subject: [PATCH] Revive line type
Change the input/output format to {A,B,C}, to match the internal
representation.
Complete the implementations of line_in, line_out, line_recv,
line_send. Remove comments and error messages about the line type not
being implemented. Add regression tests for existing line operators
and functions.
Reviewed-by: rui hua <365507506hua@gmail.com>
---
doc/src/sgml/datatype.sgml | 42 ++++-
doc/src/sgml/func.sgml | 6 +
src/backend/utils/adt/geo_ops.c | 219 ++++++++++-------------
src/include/catalog/pg_type.h | 3 +-
src/include/utils/geo_decls.h | 7 -
src/test/regress/expected/geometry.out | 3 -
src/test/regress/expected/line.out | 271 +++++++++++++++++++++++++++++
src/test/regress/expected/sanity_check.out | 3 +-
src/test/regress/output/misc.source | 3 +-
src/test/regress/parallel_schedule | 2 +-
src/test/regress/serial_schedule | 1 +
src/test/regress/sql/geometry.sql | 4 -
src/test/regress/sql/line.sql | 87 +++++++++
13 files changed, 503 insertions(+), 148 deletions(-)
create mode 100644 src/test/regress/expected/line.out
create mode 100644 src/test/regress/sql/line.sql
diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index 87668ea..07f0385 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -3051,9 +3051,7 @@ <title>Geometric Types</title>
<para>
Geometric data types represent two-dimensional spatial
objects. <xref linkend="datatype-geo-table"> shows the geometric
- types available in <productname>PostgreSQL</productname>. The
- most fundamental type, the point, forms the basis for all of the
- other types.
+ types available in <productname>PostgreSQL</productname>.
</para>
<table id="datatype-geo-table">
@@ -3063,8 +3061,8 @@ <title>Geometric Types</title>
<row>
<entry>Name</entry>
<entry>Storage Size</entry>
- <entry>Representation</entry>
<entry>Description</entry>
+ <entry>Representation</entry>
</row>
</thead>
<tbody>
@@ -3077,8 +3075,8 @@ <title>Geometric Types</title>
<row>
<entry><type>line</type></entry>
<entry>32 bytes</entry>
- <entry>Infinite line (not fully implemented)</entry>
- <entry>((x1,y1),(x2,y2))</entry>
+ <entry>Infinite line</entry>
+ <entry>{A,B,C}</entry>
</row>
<row>
<entry><type>lseg</type></entry>
@@ -3153,6 +3151,38 @@ <title>Points</title>
</sect2>
<sect2>
+ <title>Lines</title>
+
+ <indexterm>
+ <primary>line</primary>
+ </indexterm>
+
+ <para>
+ Lines (<type>line</type>) are represented by the linear equation Ax + By
+ + C = 0, where A and B are not both zero. Values of
+ type <type>line</type> is input and output in the following form:
+<synopsis>
+{ <replaceable>A</replaceable>, <replaceable>B</replaceable>, <replaceable>C</replaceable> }
+</synopsis>
+
+ Alternatively, any of the following forms can be used for input:
+
+<synopsis>
+[ ( <replaceable>x1</replaceable> , <replaceable>y1</replaceable> ) , ( <replaceable>x2</replaceable> , <replaceable>y2</replaceable> ) ]
+( ( <replaceable>x1</replaceable> , <replaceable>y1</replaceable> ) , ( <replaceable>x2</replaceable> , <replaceable>y2</replaceable> ) )
+ ( <replaceable>x1</replaceable> , <replaceable>y1</replaceable> ) , ( <replaceable>x2</replaceable> , <replaceable>y2</replaceable> )
+ <replaceable>x1</replaceable> , <replaceable>y1</replaceable> , <replaceable>x2</replaceable> , <replaceable>y2</replaceable>
+</synopsis>
+
+ where
+ <literal>(<replaceable>x1</replaceable>,<replaceable>y1</replaceable>)</literal>
+ and
+ <literal>(<replaceable>x2</replaceable>,<replaceable>y2</replaceable>)</literal>
+ are two (different) points on the line.
+ </para>
+ </sect2>
+
+ <sect2>
<title>Line Segments</title>
<indexterm>
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index ee1c957..8f60c56 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -8123,6 +8123,12 @@ <title>Geometric Type Conversion Functions</title>
<entry><literal>circle(polygon '((0,0),(1,1),(2,0))')</literal></entry>
</row>
<row>
+ <entry><literal><function>line(<type>point</type>, <type>point</type>)</function></literal></entry>
+ <entry><type>line</type></entry>
+ <entry>points to line</entry>
+ <entry><literal>line(point '(-1,0)', point '(1,0)')</literal></entry>
+ </row>
+ <row>
<entry>
<indexterm>
<primary>lseg</primary>
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index 5d0b596..6bfe6d7 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -926,42 +926,82 @@ box_diagonal(PG_FUNCTION_ARGS)
/***********************************************************************
**
** Routines for 2D lines.
- ** Lines are not intended to be used as ADTs per se,
- ** but their ops are useful tools for other ADT ops. Thus,
- ** there are few relops.
**
***********************************************************************/
+static bool
+line_decode(const char *str, LINE *line)
+{
+ char *tail;
+
+ while (isspace((unsigned char) *str))
+ str++;
+ if (*str++ != '{')
+ return false;
+ line->A = strtod(str, &tail);
+ if (tail <= str)
+ return false;
+ str = tail;
+ while (isspace((unsigned char) *str))
+ str++;
+ if (*str++ != DELIM)
+ return false;
+ line->B = strtod(str, &tail);
+ if (tail <= str)
+ return false;
+ str = tail;
+ while (isspace((unsigned char) *str))
+ str++;
+ if (*str++ != DELIM)
+ return false;
+ line->C = strtod(str, &tail);
+ if (tail <= str)
+ return false;
+ str = tail;
+ while (isspace((unsigned char) *str))
+ str++;
+ if (*str++ != '}')
+ return false;
+ while (isspace((unsigned char) *str))
+ str++;
+ if (*str)
+ return false;
+
+ return true;
+}
+
Datum
line_in(PG_FUNCTION_ARGS)
{
-#ifdef ENABLE_LINE_TYPE
char *str = PG_GETARG_CSTRING(0);
-#endif
LINE *line;
-
-#ifdef ENABLE_LINE_TYPE
- /* when fixed, modify "not implemented", catalog/pg_type.h and SGML */
LSEG lseg;
int isopen;
char *s;
- if ((!path_decode(TRUE, 2, str, &isopen, &s, &(lseg.p[0])))
- || (*s != '\0'))
+ line = (LINE *) palloc(sizeof(LINE));
+
+ if (path_decode(TRUE, 2, str, &isopen, &s, &(lseg.p[0])) && *s == '\0')
+ {
+ if (FPeq(lseg.p[0].x, lseg.p[1].x) && FPeq(lseg.p[0].y, lseg.p[1].y))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid line specification: must be two distinct points")));
+
+ line_construct_pts(line, &lseg.p[0], &lseg.p[1]);
+ }
+ else if (line_decode(str, line))
+ {
+ if (FPzero(line->A) && FPzero(line->B))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid line specification: A and B cannot both be zero")));
+ }
+ else
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type line: \"%s\"", str)));
- line = (LINE *) palloc(sizeof(LINE));
- line_construct_pts(line, &lseg.p[0], &lseg.p[1]);
-#else
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("type \"line\" not yet implemented")));
-
- line = NULL;
-#endif
-
PG_RETURN_LINE_P(line);
}
@@ -969,66 +1009,17 @@ line_in(PG_FUNCTION_ARGS)
Datum
line_out(PG_FUNCTION_ARGS)
{
-#ifdef ENABLE_LINE_TYPE
LINE *line = PG_GETARG_LINE_P(0);
-#endif
- char *result;
-
-#ifdef ENABLE_LINE_TYPE
- /* when fixed, modify "not implemented", catalog/pg_type.h and SGML */
- LSEG lseg;
-
- if (FPzero(line->B))
- { /* vertical */
- /* use "x = C" */
- result->A = -1;
- result->B = 0;
- result->C = pt1->x;
-#ifdef GEODEBUG
- printf("line_out- line is vertical\n");
-#endif
-#ifdef NOT_USED
- result->m = DBL_MAX;
-#endif
-
- }
- else if (FPzero(line->A))
- { /* horizontal */
- /* use "x = C" */
- result->A = 0;
- result->B = -1;
- result->C = pt1->y;
-#ifdef GEODEBUG
- printf("line_out- line is horizontal\n");
-#endif
-#ifdef NOT_USED
- result->m = 0.0;
-#endif
-
- }
- else
- {
- }
+ char *buf;
+ int ndig = DBL_DIG + extra_float_digits;
- if (FPzero(line->A)) /* horizontal? */
- {
- }
- else if (FPzero(line->B)) /* vertical? */
- {
- }
- else
- {
- }
+ if (ndig < 1)
+ ndig = 1;
- return path_encode(PATH_CLOSED, 2, (Point *) &(ls->p[0]));
-#else
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("type \"line\" not yet implemented")));
- result = NULL;
-#endif
+ buf = palloc(ndig * 3 + 5);
+ sprintf(buf, "{%.*g,%.*g,%.*g}", ndig, line->A, ndig, line->B, ndig, line->C);
- PG_RETURN_CSTRING(result);
+ PG_RETURN_CSTRING(buf);
}
/*
@@ -1037,10 +1028,16 @@ line_out(PG_FUNCTION_ARGS)
Datum
line_recv(PG_FUNCTION_ARGS)
{
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("type \"line\" not yet implemented")));
- return 0;
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ LINE *line;
+
+ line = (LINE *) palloc(sizeof(LINE));
+
+ line->A = pq_getmsgfloat8(buf);
+ line->B = pq_getmsgfloat8(buf);
+ line->C = pq_getmsgfloat8(buf);
+
+ PG_RETURN_LINE_P(line);
}
/*
@@ -1049,10 +1046,14 @@ line_recv(PG_FUNCTION_ARGS)
Datum
line_send(PG_FUNCTION_ARGS)
{
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("type \"line\" not yet implemented")));
- return 0;
+ LINE *line = PG_GETARG_LINE_P(0);
+ StringInfoData buf;
+
+ pq_begintypsend(&buf);
+ pq_sendfloat8(&buf, line->A);
+ pq_sendfloat8(&buf, line->B);
+ pq_sendfloat8(&buf, line->C);
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
@@ -1084,10 +1085,6 @@ line_construct_pm(Point *pt, double m)
result->C = pt->y - m * pt->x;
}
-#ifdef NOT_USED
- result->m = m;
-#endif
-
return result;
}
@@ -1103,9 +1100,6 @@ line_construct_pts(LINE *line, Point *pt1, Point *pt2)
line->A = -1;
line->B = 0;
line->C = pt1->x;
-#ifdef NOT_USED
- line->m = DBL_MAX;
-#endif
#ifdef GEODEBUG
printf("line_construct_pts- line is vertical\n");
#endif
@@ -1116,9 +1110,6 @@ line_construct_pts(LINE *line, Point *pt1, Point *pt2)
line->A = 0;
line->B = -1;
line->C = pt1->y;
-#ifdef NOT_USED
- line->m = 0.0;
-#endif
#ifdef GEODEBUG
printf("line_construct_pts- line is horizontal\n");
#endif
@@ -1129,9 +1120,6 @@ line_construct_pts(LINE *line, Point *pt1, Point *pt2)
line->A = (pt2->y - pt1->y) / (pt2->x - pt1->x);
line->B = -1.0;
line->C = pt1->y - line->A * pt1->x;
-#ifdef NOT_USED
- line->m = line->A;
-#endif
#ifdef GEODEBUG
printf("line_construct_pts- line is neither vertical nor horizontal (diffs x=%.*g, y=%.*g\n",
DBL_DIG, (pt2->x - pt1->x), DBL_DIG, (pt2->y - pt1->y));
@@ -1175,9 +1163,6 @@ line_parallel(PG_FUNCTION_ARGS)
LINE *l1 = PG_GETARG_LINE_P(0);
LINE *l2 = PG_GETARG_LINE_P(1);
-#ifdef NOT_USED
- PG_RETURN_BOOL(FPeq(l1->m, l2->m));
-#endif
if (FPzero(l1->B))
PG_RETURN_BOOL(FPzero(l2->B));
@@ -1190,12 +1175,6 @@ line_perp(PG_FUNCTION_ARGS)
LINE *l1 = PG_GETARG_LINE_P(0);
LINE *l2 = PG_GETARG_LINE_P(1);
-#ifdef NOT_USED
- if (l1->m)
- PG_RETURN_BOOL(FPeq(l2->m / l1->m, -1.0));
- else if (l2->m)
- PG_RETURN_BOOL(FPeq(l1->m / l2->m, -1.0));
-#endif
if (FPzero(l1->A))
PG_RETURN_BOOL(FPzero(l2->B));
else if (FPzero(l1->B))
@@ -1307,18 +1286,6 @@ line_interpt_internal(LINE *l1, LINE *l2)
LinePGetDatum(l2))))
return NULL;
-#ifdef NOT_USED
- if (FPzero(l1->B)) /* l1 vertical? */
- result = point_construct(l2->m * l1->C + l2->C, l1->C);
- else if (FPzero(l2->B)) /* l2 vertical? */
- result = point_construct(l1->m * l2->C + l1->C, l2->C);
- else
- {
- x = (l1->C - l2->C) / (l2->A - l1->A);
- result = point_construct(x, l1->m * x + l1->C);
- }
-#endif
-
if (FPzero(l1->B)) /* l1 vertical? */
{
x = l1->C;
@@ -2449,8 +2416,8 @@ dist_pl(PG_FUNCTION_ARGS)
static double
dist_pl_internal(Point *pt, LINE *line)
{
- return (line->A * pt->x + line->B * pt->y + line->C) /
- HYPOT(line->A, line->B);
+ return fabs((line->A * pt->x + line->B * pt->y + line->C) /
+ HYPOT(line->A, line->B));
}
Datum
@@ -2789,9 +2756,7 @@ close_pl(PG_FUNCTION_ARGS)
PG_RETURN_POINT_P(result);
}
/* drop a perpendicular and find the intersection point */
-#ifdef NOT_USED
- invm = -1.0 / line->m;
-#endif
+
/* invert and flip the sign on the slope to get a perpendicular */
invm = line->B / line->A;
tmp = line_construct_pm(pt, invm);
@@ -3038,6 +3003,7 @@ close_pb(PG_FUNCTION_ARGS)
Datum
close_sl(PG_FUNCTION_ARGS)
{
+#ifdef NOT_USED
LSEG *lseg = PG_GETARG_LSEG_P(0);
LINE *line = PG_GETARG_LINE_P(1);
Point *result;
@@ -3056,6 +3022,13 @@ close_sl(PG_FUNCTION_ARGS)
result = point_copy(&lseg->p[1]);
PG_RETURN_POINT_P(result);
+#endif
+
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("function \"close_sl\" not implemented")));
+
+ PG_RETURN_NULL();
}
/* close_ls()
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index e3822fa..2081312 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -393,10 +393,9 @@ DESCR("geometric polygon '(pt1,...)'");
#define POLYGONOID 604
DATA(insert OID = 628 ( line PGNSP PGUID 32 f b G f t \054 0 701 629 line_in line_out line_recv line_send - - - d p f 0 -1 0 0 _null_ _null_ _null_ ));
-DESCR("geometric line (not implemented)");
+DESCR("geometric line");
#define LINEOID 628
DATA(insert OID = 629 ( _line PGNSP PGUID -1 f b A f t \054 0 628 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DESCR("");
/* OIDS 700 - 799 */
diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h
index 5c83a71..1e648c0 100644
--- a/src/include/utils/geo_decls.h
+++ b/src/include/utils/geo_decls.h
@@ -88,19 +88,12 @@ typedef struct
/*---------------------------------------------------------------------
* LINE - Specified by its general equation (Ax+By+C=0).
- * If there is a y-intercept, it is C, which
- * incidentally gives a freebie point on the line
- * (if B=0, then C is the x-intercept).
- * Slope m is precalculated to save time; if
- * the line is not vertical, m == A.
*-------------------------------------------------------------------*/
typedef struct
{
double A,
B,
C;
-
- double m;
} LINE;
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index 8123725..21ad555 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -146,9 +146,6 @@ SELECT '' AS thirty, p.f1, l.s, p.f1 ## l.s AS closest
(30 rows)
--
--- Lines
---
---
-- Boxes
--
SELECT '' as six, box(f1) AS box FROM CIRCLE_TBL;
diff --git a/src/test/regress/expected/line.out b/src/test/regress/expected/line.out
new file mode 100644
index 0000000..7d222fc
--- /dev/null
+++ b/src/test/regress/expected/line.out
@@ -0,0 +1,271 @@
+--
+-- LINE
+-- Infinite lines
+--
+--DROP TABLE LINE_TBL;
+CREATE TABLE LINE_TBL (s line);
+INSERT INTO LINE_TBL VALUES ('{1,-1,1}');
+INSERT INTO LINE_TBL VALUES ('(0,0),(6,6)');
+INSERT INTO LINE_TBL VALUES ('10,-10 ,-3,-4');
+INSERT INTO LINE_TBL VALUES ('[-1e6,2e2,3e5, -4e1]');
+INSERT INTO LINE_TBL VALUES ('(11,22,33,44)');
+INSERT INTO LINE_TBL VALUES ('[(1,0),(1,0)]');
+ERROR: invalid line specification: must be two distinct points
+LINE 1: INSERT INTO LINE_TBL VALUES ('[(1,0),(1,0)]');
+ ^
+-- horizontal
+INSERT INTO LINE_TBL VALUES ('[(1,3),(2,3)]');
+-- vertical
+INSERT INTO LINE_TBL VALUES ('[(3,1),(3,2)]');
+-- bad values for parser testing
+INSERT INTO LINE_TBL VALUES ('{0,0,1}');
+ERROR: invalid line specification: A and B cannot both be zero
+LINE 1: INSERT INTO LINE_TBL VALUES ('{0,0,1}');
+ ^
+INSERT INTO LINE_TBL VALUES ('(3asdf,2 ,3,4r2)');
+ERROR: invalid input syntax for type line: "(3asdf,2 ,3,4r2)"
+LINE 1: INSERT INTO LINE_TBL VALUES ('(3asdf,2 ,3,4r2)');
+ ^
+INSERT INTO LINE_TBL VALUES ('[1,2,3, 4');
+ERROR: invalid input syntax for type line: "[1,2,3, 4"
+LINE 1: INSERT INTO LINE_TBL VALUES ('[1,2,3, 4');
+ ^
+INSERT INTO LINE_TBL VALUES ('[(,2),(3,4)]');
+ERROR: invalid input syntax for type line: "[(,2),(3,4)]"
+LINE 1: INSERT INTO LINE_TBL VALUES ('[(,2),(3,4)]');
+ ^
+INSERT INTO LINE_TBL VALUES ('[(1,2),(3,4)');
+ERROR: invalid input syntax for type line: "[(1,2),(3,4)"
+LINE 1: INSERT INTO LINE_TBL VALUES ('[(1,2),(3,4)');
+ ^
+select * from LINE_TBL;
+ s
+---------------------------------------------
+ {1,-1,1}
+ {1,-1,0}
+ {-0.461538461538462,-1,-5.38461538461538}
+ {-0.000184615384615385,-1,15.3846153846154}
+ {1,-1,11}
+ {0,-1,3}
+ {-1,0,3}
+(7 rows)
+
+-- functions and operators
+SELECT * FROM LINE_TBL WHERE (s <-> line '[(1,2),(3,4)]') < 10;
+ s
+---------------------------------------------
+ {1,-1,1}
+ {1,-1,0}
+ {-0.461538461538462,-1,-5.38461538461538}
+ {-0.000184615384615385,-1,15.3846153846154}
+ {1,-1,11}
+ {0,-1,3}
+ {-1,0,3}
+(7 rows)
+
+SELECT * FROM LINE_TBL WHERE (point '(0.1,0.1)' <-> s) < 1;
+ s
+----------
+ {1,-1,1}
+ {1,-1,0}
+(2 rows)
+
+SELECT * FROM LINE_TBL WHERE (lseg '[(0.1,0.1),(0.2,0.2)]' <-> s) < 1;
+ s
+----------
+ {1,-1,1}
+ {1,-1,0}
+(2 rows)
+
+SELECT line '[(1,1),(2,1)]' <-> line '[(-1,-1),(-2,-1)]';
+ ?column?
+----------
+ 2
+(1 row)
+
+SELECT lseg '[(1,1),(2,1)]' <-> line '[(-1,-1),(-2,-1)]';
+ ?column?
+----------
+ 2
+(1 row)
+
+SELECT point '(-1,1)' <-> line '[(-3,0),(-4,0)]';
+ ?column?
+----------
+ 1
+(1 row)
+
+SELECT lseg '[(1,1),(5,5)]' ?# line '[(2,0),(0,2)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT lseg '[(1,1),(5,5)]' ?# line '[(0,0),(1,0)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ?# box '(0,0,2,2)'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT line '[(3,0),(4,1)]' ?# box '(0,0,2,2)'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT point '(1,1)' <@ line '[(0,0),(2,2)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT point '(1,1)' <@ line '[(0,0),(1,0)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT point '(1,1)' @ line '[(0,0),(2,2)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT point '(1,1)' @ line '[(0,0),(1,0)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT lseg '[(1,1),(2,2)]' <@ line '[(0,0),(2,2)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT lseg '[(1,1),(2,1)]' <@ line '[(0,0),(1,0)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT lseg '[(1,1),(2,2)]' @ line '[(0,0),(2,2)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT lseg '[(1,1),(2,1)]' @ line '[(0,0),(1,0)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT point '(0,1)' ## line '[(0,0),(1,1)]';
+ ?column?
+-----------
+ (0.5,0.5)
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ## lseg '[(1,0),(2,0)]';
+ ?column?
+----------
+ (1,0)
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ?# line '[(1,0),(2,1)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ?# line '[(1,0),(1,1)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' # line '[(1,0),(2,1)]';
+ ?column?
+----------
+
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' # line '[(1,0),(1,1)]';
+ ?column?
+----------
+ (1,1)
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ?|| line '[(1,0),(2,1)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ?|| line '[(1,0),(1,1)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT line '[(0,0),(1,0)]' ?-| line '[(0,0),(0,1)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ?-| line '[(1,0),(1,1)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT ?- line '[(0,0),(1,0)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT ?- line '[(0,0),(1,1)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT ?| line '[(0,0),(0,1)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT ?| line '[(0,0),(1,1)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT line(point '(1,2)', point '(3,4)');
+ line
+----------
+ {1,-1,1}
+(1 row)
+
+SELECT line '[(1,2),(3,4)]' = line '[(3,4),(4,5)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT line '[(1,2),(3,4)]' = line '[(3,4),(4,4)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index 432d39a..cee35af 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -64,6 +64,7 @@ SELECT relname, relhasindex
interval_tbl | f
iportaltest | f
kd_point_tbl | t
+ line_tbl | f
log_table | f
lseg_tbl | f
main_table | f
@@ -166,7 +167,7 @@ SELECT relname, relhasindex
timetz_tbl | f
tinterval_tbl | f
varchar_tbl | f
-(155 rows)
+(156 rows)
--
-- another sanity check: every system catalog that has OIDs should have
diff --git a/src/test/regress/output/misc.source b/src/test/regress/output/misc.source
index 29cbb22..e194f7e 100644
--- a/src/test/regress/output/misc.source
+++ b/src/test/regress/output/misc.source
@@ -638,6 +638,7 @@ SELECT user_relns() AS user_relns
interval_tbl
iportaltest
kd_point_tbl
+ line_tbl
log_table
lseg_tbl
main_table
@@ -696,7 +697,7 @@ SELECT user_relns() AS user_relns
tvvmv
varchar_tbl
xacttest
-(118 rows)
+(119 rows)
SELECT name(equipment(hobby_construct(text 'skywalking', text 'mer')));
name
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index fd08e8d..1c1491c 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -23,7 +23,7 @@ test: numerology
# ----------
# The second group of parallel tests
# ----------
-test: point lseg box path polygon circle date time timetz timestamp timestamptz interval abstime reltime tinterval inet macaddr tstypes comments
+test: point lseg line box path polygon circle date time timetz timestamp timestamptz interval abstime reltime tinterval inet macaddr tstypes comments
# ----------
# Another group of parallel tests
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index 1ed059b..c4d451a 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -23,6 +23,7 @@ test: strings
test: numerology
test: point
test: lseg
+test: line
test: box
test: path
test: polygon
diff --git a/src/test/regress/sql/geometry.sql b/src/test/regress/sql/geometry.sql
index 73f8032..af7f8a5 100644
--- a/src/test/regress/sql/geometry.sql
+++ b/src/test/regress/sql/geometry.sql
@@ -59,10 +59,6 @@
FROM LSEG_TBL l, POINT_TBL p;
--
--- Lines
---
-
---
-- Boxes
--
diff --git a/src/test/regress/sql/line.sql b/src/test/regress/sql/line.sql
new file mode 100644
index 0000000..cd9280b
--- /dev/null
+++ b/src/test/regress/sql/line.sql
@@ -0,0 +1,87 @@
+--
+-- LINE
+-- Infinite lines
+--
+
+--DROP TABLE LINE_TBL;
+CREATE TABLE LINE_TBL (s line);
+
+INSERT INTO LINE_TBL VALUES ('{1,-1,1}');
+INSERT INTO LINE_TBL VALUES ('(0,0),(6,6)');
+INSERT INTO LINE_TBL VALUES ('10,-10 ,-3,-4');
+INSERT INTO LINE_TBL VALUES ('[-1e6,2e2,3e5, -4e1]');
+INSERT INTO LINE_TBL VALUES ('(11,22,33,44)');
+
+INSERT INTO LINE_TBL VALUES ('[(1,0),(1,0)]');
+
+-- horizontal
+INSERT INTO LINE_TBL VALUES ('[(1,3),(2,3)]');
+-- vertical
+INSERT INTO LINE_TBL VALUES ('[(3,1),(3,2)]');
+
+-- bad values for parser testing
+INSERT INTO LINE_TBL VALUES ('{0,0,1}');
+INSERT INTO LINE_TBL VALUES ('(3asdf,2 ,3,4r2)');
+INSERT INTO LINE_TBL VALUES ('[1,2,3, 4');
+INSERT INTO LINE_TBL VALUES ('[(,2),(3,4)]');
+INSERT INTO LINE_TBL VALUES ('[(1,2),(3,4)');
+
+select * from LINE_TBL;
+
+
+-- functions and operators
+
+SELECT * FROM LINE_TBL WHERE (s <-> line '[(1,2),(3,4)]') < 10;
+
+SELECT * FROM LINE_TBL WHERE (point '(0.1,0.1)' <-> s) < 1;
+
+SELECT * FROM LINE_TBL WHERE (lseg '[(0.1,0.1),(0.2,0.2)]' <-> s) < 1;
+
+SELECT line '[(1,1),(2,1)]' <-> line '[(-1,-1),(-2,-1)]';
+SELECT lseg '[(1,1),(2,1)]' <-> line '[(-1,-1),(-2,-1)]';
+SELECT point '(-1,1)' <-> line '[(-3,0),(-4,0)]';
+
+SELECT lseg '[(1,1),(5,5)]' ?# line '[(2,0),(0,2)]'; -- true
+SELECT lseg '[(1,1),(5,5)]' ?# line '[(0,0),(1,0)]'; -- false
+
+SELECT line '[(0,0),(1,1)]' ?# box '(0,0,2,2)'; -- true
+SELECT line '[(3,0),(4,1)]' ?# box '(0,0,2,2)'; -- false
+
+SELECT point '(1,1)' <@ line '[(0,0),(2,2)]'; -- true
+SELECT point '(1,1)' <@ line '[(0,0),(1,0)]'; -- false
+
+SELECT point '(1,1)' @ line '[(0,0),(2,2)]'; -- true
+SELECT point '(1,1)' @ line '[(0,0),(1,0)]'; -- false
+
+SELECT lseg '[(1,1),(2,2)]' <@ line '[(0,0),(2,2)]'; -- true
+SELECT lseg '[(1,1),(2,1)]' <@ line '[(0,0),(1,0)]'; -- false
+
+SELECT lseg '[(1,1),(2,2)]' @ line '[(0,0),(2,2)]'; -- true
+SELECT lseg '[(1,1),(2,1)]' @ line '[(0,0),(1,0)]'; -- false
+
+SELECT point '(0,1)' ## line '[(0,0),(1,1)]';
+
+SELECT line '[(0,0),(1,1)]' ## lseg '[(1,0),(2,0)]';
+
+SELECT line '[(0,0),(1,1)]' ?# line '[(1,0),(2,1)]'; -- false
+SELECT line '[(0,0),(1,1)]' ?# line '[(1,0),(1,1)]'; -- true
+
+SELECT line '[(0,0),(1,1)]' # line '[(1,0),(2,1)]';
+SELECT line '[(0,0),(1,1)]' # line '[(1,0),(1,1)]';
+
+SELECT line '[(0,0),(1,1)]' ?|| line '[(1,0),(2,1)]'; -- true
+SELECT line '[(0,0),(1,1)]' ?|| line '[(1,0),(1,1)]'; -- false
+
+SELECT line '[(0,0),(1,0)]' ?-| line '[(0,0),(0,1)]'; -- true
+SELECT line '[(0,0),(1,1)]' ?-| line '[(1,0),(1,1)]'; -- false
+
+SELECT ?- line '[(0,0),(1,0)]'; -- true
+SELECT ?- line '[(0,0),(1,1)]'; -- false
+
+SELECT ?| line '[(0,0),(0,1)]'; -- true
+SELECT ?| line '[(0,0),(1,1)]'; -- false
+
+SELECT line(point '(1,2)', point '(3,4)');
+
+SELECT line '[(1,2),(3,4)]' = line '[(3,4),(4,5)]'; -- true
+SELECT line '[(1,2),(3,4)]' = line '[(3,4),(4,4)]'; -- false
--
1.8.4.rc3
Peter Eisentraut escribi�:
Here is a new patch for the line type, with a new input/output format
{A,B,C}, as discussed in this thread.
I gave this a quick look. The new input/output format appears to work
well. The input format using two points still works, which is nice.
Regression tests pass. I tried binary input and output using COPY and
it seems to round-trip without problem.
With the two-point input, horizontal and vertical lines can accept NaNs
without producing a NaN in the output if not necessary.
I tried "interpt" and "intersect" functions and they seem to work.
Haven't gotten around to trying other functions or operators.
--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Mon, Sep 16, 2013 at 07:04:32PM -0300, Alvaro Herrera wrote:
Peter Eisentraut escribi�:
Here is a new patch for the line type, with a new input/output format
{A,B,C}, as discussed in this thread.I gave this a quick look. The new input/output format appears to work
well. The input format using two points still works, which is nice.
Regression tests pass. I tried binary input and output using COPY and
it seems to round-trip without problem.With the two-point input, horizontal and vertical lines can accept NaNs
without producing a NaN in the output if not necessary.I tried "interpt" and "intersect" functions and they seem to work.
Haven't gotten around to trying other functions or operators.
Should the things you tried and others be in the regression tests? If
so, should we start with whatever had been in the regression tests
when the line type was dropped?
Cheers,
David.
--
David Fetter <david@fetter.org> http://fetter.org/
Phone: +1 415 235 3778 AIM: dfetter666 Yahoo!: dfetter
Skype: davidfetter XMPP: david.fetter@gmail.com
iCal: webcal://www.tripit.com/feed/ical/people/david74/tripit.ics
Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
David Fetter escribi�:
Should the things you tried and others be in the regression tests? If
so, should we start with whatever had been in the regression tests
when the line type was dropped?
Actually, the patch does include a regression test for the revived type
(and it passes). I don't think more than that is needed.
--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
Hi,
I had a look over this patch and here are my review points:
1. Patch applies cleanly.
2. make, make install and make check is good.
3. I did lot of random testing and didn't find any issue.
4. Test coverage is very well. It has all scenarios and all operators are
tested with line. That's really great.
So no issues from my side.
However, do we still need this in close_pl() ?
#ifdef NOT_USED
if (FPeq(line->A, -1.0) && FPzero(line->B))
{ /* vertical */
}
#endif
Also close_sl, close_lb and dist_lb are NOT yet implemented. It will be good
if we have those. But I don't think we should wait for those functions to be
implemented. We can go ahead with this. Please confirm above concern so that
I will mark it as "Ready for Committer".
Thanks
On Tue, Sep 17, 2013 at 7:34 AM, Alvaro Herrera <alvherre@2ndquadrant.com>wrote:
David Fetter escribió:
Should the things you tried and others be in the regression tests? If
so, should we start with whatever had been in the regression tests
when the line type was dropped?Actually, the patch does include a regression test for the revived type
(and it passes). I don't think more than that is needed.--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
--
Jeevan B Chalke
Principal Software Engineer, Product Development
EnterpriseDB Corporation
On Wed, 2013-09-25 at 14:26 +0530, Jeevan Chalke wrote:
So no issues from my side.
However, do we still need this in close_pl() ?
#ifdef NOT_USED
if (FPeq(line->A, -1.0) && FPzero(line->B))
{ /* vertical */
}
#endif
No, that can be removed.
Also close_sl, close_lb and dist_lb are NOT yet implemented. It will
be good if we have those. But I don't think we should wait for those
functions to be implemented.
Right, those are separate projects.
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Wed, Oct 2, 2013 at 6:12 AM, Peter Eisentraut <peter_e@gmx.net> wrote:
On Wed, 2013-09-25 at 14:26 +0530, Jeevan Chalke wrote:
So no issues from my side.
However, do we still need this in close_pl() ?
#ifdef NOT_USED
if (FPeq(line->A, -1.0) && FPzero(line->B))
{ /* vertical */
}
#endifNo, that can be removed.
Will you please attach new patch with above block removed ? Then I will
quickly check that new patch and mark as "Ready For Committer".
Also close_sl, close_lb and dist_lb are NOT yet implemented. It will
be good if we have those. But I don't think we should wait for those
functions to be implemented.Right, those are separate projects.
Agree.
Thanks
--
Jeevan B Chalke
On Thu, 2013-10-03 at 17:50 +0530, Jeevan Chalke wrote:
Will you please attach new patch with above block removed ? Then I
will quickly check that new patch and mark as "Ready For Committer".
Here you go.
Attachments:
v2-0001-Revive-line-type.patchtext/x-patch; charset=UTF-8; name=v2-0001-Revive-line-type.patchDownload
From ba421c778cc3f7c32886ac038389cfbad3c0df67 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter_e@gmx.net>
Date: Wed, 9 Oct 2013 01:09:18 -0400
Subject: [PATCH v2] Revive line type
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Change the input/output format to {A,B,C}, to match the internal
representation.
Complete the implementations of line_in, line_out, line_recv, line_send.
Remove comments and error messages about the line type not being
implemented. Add regression tests for existing line operators and
functions.
Reviewed-by: rui hua <365507506hua@gmail.com>
Reviewed-by: Álvaro Herrera <alvherre@2ndquadrant.com>
Reviewed-by: Jeevan Chalke <jeevan.chalke@enterprisedb.com>
---
doc/src/sgml/datatype.sgml | 42 ++++-
doc/src/sgml/func.sgml | 6 +
src/backend/utils/adt/geo_ops.c | 224 ++++++++++--------------
src/include/catalog/pg_type.h | 3 +-
src/include/utils/geo_decls.h | 7 -
src/test/regress/expected/geometry.out | 3 -
src/test/regress/expected/line.out | 271 +++++++++++++++++++++++++++++
src/test/regress/expected/sanity_check.out | 3 +-
src/test/regress/output/misc.source | 3 +-
src/test/regress/parallel_schedule | 2 +-
src/test/regress/serial_schedule | 1 +
src/test/regress/sql/geometry.sql | 4 -
src/test/regress/sql/line.sql | 87 +++++++++
13 files changed, 503 insertions(+), 153 deletions(-)
create mode 100644 src/test/regress/expected/line.out
create mode 100644 src/test/regress/sql/line.sql
diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index 87668ea..07f0385 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -3051,9 +3051,7 @@ <title>Geometric Types</title>
<para>
Geometric data types represent two-dimensional spatial
objects. <xref linkend="datatype-geo-table"> shows the geometric
- types available in <productname>PostgreSQL</productname>. The
- most fundamental type, the point, forms the basis for all of the
- other types.
+ types available in <productname>PostgreSQL</productname>.
</para>
<table id="datatype-geo-table">
@@ -3063,8 +3061,8 @@ <title>Geometric Types</title>
<row>
<entry>Name</entry>
<entry>Storage Size</entry>
- <entry>Representation</entry>
<entry>Description</entry>
+ <entry>Representation</entry>
</row>
</thead>
<tbody>
@@ -3077,8 +3075,8 @@ <title>Geometric Types</title>
<row>
<entry><type>line</type></entry>
<entry>32 bytes</entry>
- <entry>Infinite line (not fully implemented)</entry>
- <entry>((x1,y1),(x2,y2))</entry>
+ <entry>Infinite line</entry>
+ <entry>{A,B,C}</entry>
</row>
<row>
<entry><type>lseg</type></entry>
@@ -3153,6 +3151,38 @@ <title>Points</title>
</sect2>
<sect2>
+ <title>Lines</title>
+
+ <indexterm>
+ <primary>line</primary>
+ </indexterm>
+
+ <para>
+ Lines (<type>line</type>) are represented by the linear equation Ax + By
+ + C = 0, where A and B are not both zero. Values of
+ type <type>line</type> is input and output in the following form:
+<synopsis>
+{ <replaceable>A</replaceable>, <replaceable>B</replaceable>, <replaceable>C</replaceable> }
+</synopsis>
+
+ Alternatively, any of the following forms can be used for input:
+
+<synopsis>
+[ ( <replaceable>x1</replaceable> , <replaceable>y1</replaceable> ) , ( <replaceable>x2</replaceable> , <replaceable>y2</replaceable> ) ]
+( ( <replaceable>x1</replaceable> , <replaceable>y1</replaceable> ) , ( <replaceable>x2</replaceable> , <replaceable>y2</replaceable> ) )
+ ( <replaceable>x1</replaceable> , <replaceable>y1</replaceable> ) , ( <replaceable>x2</replaceable> , <replaceable>y2</replaceable> )
+ <replaceable>x1</replaceable> , <replaceable>y1</replaceable> , <replaceable>x2</replaceable> , <replaceable>y2</replaceable>
+</synopsis>
+
+ where
+ <literal>(<replaceable>x1</replaceable>,<replaceable>y1</replaceable>)</literal>
+ and
+ <literal>(<replaceable>x2</replaceable>,<replaceable>y2</replaceable>)</literal>
+ are two (different) points on the line.
+ </para>
+ </sect2>
+
+ <sect2>
<title>Line Segments</title>
<indexterm>
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 7dd1ef2..b162618 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -8123,6 +8123,12 @@ <title>Geometric Type Conversion Functions</title>
<entry><literal>circle(polygon '((0,0),(1,1),(2,0))')</literal></entry>
</row>
<row>
+ <entry><literal><function>line(<type>point</type>, <type>point</type>)</function></literal></entry>
+ <entry><type>line</type></entry>
+ <entry>points to line</entry>
+ <entry><literal>line(point '(-1,0)', point '(1,0)')</literal></entry>
+ </row>
+ <row>
<entry>
<indexterm>
<primary>lseg</primary>
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index 5d0b596..b792d26 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -926,42 +926,82 @@ box_diagonal(PG_FUNCTION_ARGS)
/***********************************************************************
**
** Routines for 2D lines.
- ** Lines are not intended to be used as ADTs per se,
- ** but their ops are useful tools for other ADT ops. Thus,
- ** there are few relops.
**
***********************************************************************/
+static bool
+line_decode(const char *str, LINE *line)
+{
+ char *tail;
+
+ while (isspace((unsigned char) *str))
+ str++;
+ if (*str++ != '{')
+ return false;
+ line->A = strtod(str, &tail);
+ if (tail <= str)
+ return false;
+ str = tail;
+ while (isspace((unsigned char) *str))
+ str++;
+ if (*str++ != DELIM)
+ return false;
+ line->B = strtod(str, &tail);
+ if (tail <= str)
+ return false;
+ str = tail;
+ while (isspace((unsigned char) *str))
+ str++;
+ if (*str++ != DELIM)
+ return false;
+ line->C = strtod(str, &tail);
+ if (tail <= str)
+ return false;
+ str = tail;
+ while (isspace((unsigned char) *str))
+ str++;
+ if (*str++ != '}')
+ return false;
+ while (isspace((unsigned char) *str))
+ str++;
+ if (*str)
+ return false;
+
+ return true;
+}
+
Datum
line_in(PG_FUNCTION_ARGS)
{
-#ifdef ENABLE_LINE_TYPE
char *str = PG_GETARG_CSTRING(0);
-#endif
LINE *line;
-
-#ifdef ENABLE_LINE_TYPE
- /* when fixed, modify "not implemented", catalog/pg_type.h and SGML */
LSEG lseg;
int isopen;
char *s;
- if ((!path_decode(TRUE, 2, str, &isopen, &s, &(lseg.p[0])))
- || (*s != '\0'))
+ line = (LINE *) palloc(sizeof(LINE));
+
+ if (path_decode(TRUE, 2, str, &isopen, &s, &(lseg.p[0])) && *s == '\0')
+ {
+ if (FPeq(lseg.p[0].x, lseg.p[1].x) && FPeq(lseg.p[0].y, lseg.p[1].y))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid line specification: must be two distinct points")));
+
+ line_construct_pts(line, &lseg.p[0], &lseg.p[1]);
+ }
+ else if (line_decode(str, line))
+ {
+ if (FPzero(line->A) && FPzero(line->B))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid line specification: A and B cannot both be zero")));
+ }
+ else
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type line: \"%s\"", str)));
- line = (LINE *) palloc(sizeof(LINE));
- line_construct_pts(line, &lseg.p[0], &lseg.p[1]);
-#else
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("type \"line\" not yet implemented")));
-
- line = NULL;
-#endif
-
PG_RETURN_LINE_P(line);
}
@@ -969,66 +1009,17 @@ line_in(PG_FUNCTION_ARGS)
Datum
line_out(PG_FUNCTION_ARGS)
{
-#ifdef ENABLE_LINE_TYPE
LINE *line = PG_GETARG_LINE_P(0);
-#endif
- char *result;
-
-#ifdef ENABLE_LINE_TYPE
- /* when fixed, modify "not implemented", catalog/pg_type.h and SGML */
- LSEG lseg;
-
- if (FPzero(line->B))
- { /* vertical */
- /* use "x = C" */
- result->A = -1;
- result->B = 0;
- result->C = pt1->x;
-#ifdef GEODEBUG
- printf("line_out- line is vertical\n");
-#endif
-#ifdef NOT_USED
- result->m = DBL_MAX;
-#endif
-
- }
- else if (FPzero(line->A))
- { /* horizontal */
- /* use "x = C" */
- result->A = 0;
- result->B = -1;
- result->C = pt1->y;
-#ifdef GEODEBUG
- printf("line_out- line is horizontal\n");
-#endif
-#ifdef NOT_USED
- result->m = 0.0;
-#endif
-
- }
- else
- {
- }
+ char *buf;
+ int ndig = DBL_DIG + extra_float_digits;
- if (FPzero(line->A)) /* horizontal? */
- {
- }
- else if (FPzero(line->B)) /* vertical? */
- {
- }
- else
- {
- }
+ if (ndig < 1)
+ ndig = 1;
- return path_encode(PATH_CLOSED, 2, (Point *) &(ls->p[0]));
-#else
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("type \"line\" not yet implemented")));
- result = NULL;
-#endif
+ buf = palloc(ndig * 3 + 5);
+ sprintf(buf, "{%.*g,%.*g,%.*g}", ndig, line->A, ndig, line->B, ndig, line->C);
- PG_RETURN_CSTRING(result);
+ PG_RETURN_CSTRING(buf);
}
/*
@@ -1037,10 +1028,16 @@ line_out(PG_FUNCTION_ARGS)
Datum
line_recv(PG_FUNCTION_ARGS)
{
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("type \"line\" not yet implemented")));
- return 0;
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ LINE *line;
+
+ line = (LINE *) palloc(sizeof(LINE));
+
+ line->A = pq_getmsgfloat8(buf);
+ line->B = pq_getmsgfloat8(buf);
+ line->C = pq_getmsgfloat8(buf);
+
+ PG_RETURN_LINE_P(line);
}
/*
@@ -1049,10 +1046,14 @@ line_recv(PG_FUNCTION_ARGS)
Datum
line_send(PG_FUNCTION_ARGS)
{
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("type \"line\" not yet implemented")));
- return 0;
+ LINE *line = PG_GETARG_LINE_P(0);
+ StringInfoData buf;
+
+ pq_begintypsend(&buf);
+ pq_sendfloat8(&buf, line->A);
+ pq_sendfloat8(&buf, line->B);
+ pq_sendfloat8(&buf, line->C);
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
@@ -1084,10 +1085,6 @@ line_construct_pm(Point *pt, double m)
result->C = pt->y - m * pt->x;
}
-#ifdef NOT_USED
- result->m = m;
-#endif
-
return result;
}
@@ -1103,9 +1100,6 @@ line_construct_pts(LINE *line, Point *pt1, Point *pt2)
line->A = -1;
line->B = 0;
line->C = pt1->x;
-#ifdef NOT_USED
- line->m = DBL_MAX;
-#endif
#ifdef GEODEBUG
printf("line_construct_pts- line is vertical\n");
#endif
@@ -1116,9 +1110,6 @@ line_construct_pts(LINE *line, Point *pt1, Point *pt2)
line->A = 0;
line->B = -1;
line->C = pt1->y;
-#ifdef NOT_USED
- line->m = 0.0;
-#endif
#ifdef GEODEBUG
printf("line_construct_pts- line is horizontal\n");
#endif
@@ -1129,9 +1120,6 @@ line_construct_pts(LINE *line, Point *pt1, Point *pt2)
line->A = (pt2->y - pt1->y) / (pt2->x - pt1->x);
line->B = -1.0;
line->C = pt1->y - line->A * pt1->x;
-#ifdef NOT_USED
- line->m = line->A;
-#endif
#ifdef GEODEBUG
printf("line_construct_pts- line is neither vertical nor horizontal (diffs x=%.*g, y=%.*g\n",
DBL_DIG, (pt2->x - pt1->x), DBL_DIG, (pt2->y - pt1->y));
@@ -1175,9 +1163,6 @@ line_parallel(PG_FUNCTION_ARGS)
LINE *l1 = PG_GETARG_LINE_P(0);
LINE *l2 = PG_GETARG_LINE_P(1);
-#ifdef NOT_USED
- PG_RETURN_BOOL(FPeq(l1->m, l2->m));
-#endif
if (FPzero(l1->B))
PG_RETURN_BOOL(FPzero(l2->B));
@@ -1190,12 +1175,6 @@ line_perp(PG_FUNCTION_ARGS)
LINE *l1 = PG_GETARG_LINE_P(0);
LINE *l2 = PG_GETARG_LINE_P(1);
-#ifdef NOT_USED
- if (l1->m)
- PG_RETURN_BOOL(FPeq(l2->m / l1->m, -1.0));
- else if (l2->m)
- PG_RETURN_BOOL(FPeq(l1->m / l2->m, -1.0));
-#endif
if (FPzero(l1->A))
PG_RETURN_BOOL(FPzero(l2->B));
else if (FPzero(l1->B))
@@ -1307,18 +1286,6 @@ line_interpt_internal(LINE *l1, LINE *l2)
LinePGetDatum(l2))))
return NULL;
-#ifdef NOT_USED
- if (FPzero(l1->B)) /* l1 vertical? */
- result = point_construct(l2->m * l1->C + l2->C, l1->C);
- else if (FPzero(l2->B)) /* l2 vertical? */
- result = point_construct(l1->m * l2->C + l1->C, l2->C);
- else
- {
- x = (l1->C - l2->C) / (l2->A - l1->A);
- result = point_construct(x, l1->m * x + l1->C);
- }
-#endif
-
if (FPzero(l1->B)) /* l1 vertical? */
{
x = l1->C;
@@ -2449,8 +2416,8 @@ dist_pl(PG_FUNCTION_ARGS)
static double
dist_pl_internal(Point *pt, LINE *line)
{
- return (line->A * pt->x + line->B * pt->y + line->C) /
- HYPOT(line->A, line->B);
+ return fabs((line->A * pt->x + line->B * pt->y + line->C) /
+ HYPOT(line->A, line->B));
}
Datum
@@ -2771,11 +2738,6 @@ close_pl(PG_FUNCTION_ARGS)
result = (Point *) palloc(sizeof(Point));
-#ifdef NOT_USED
- if (FPeq(line->A, -1.0) && FPzero(line->B))
- { /* vertical */
- }
-#endif
if (FPzero(line->B)) /* vertical? */
{
result->x = line->C;
@@ -2789,9 +2751,7 @@ close_pl(PG_FUNCTION_ARGS)
PG_RETURN_POINT_P(result);
}
/* drop a perpendicular and find the intersection point */
-#ifdef NOT_USED
- invm = -1.0 / line->m;
-#endif
+
/* invert and flip the sign on the slope to get a perpendicular */
invm = line->B / line->A;
tmp = line_construct_pm(pt, invm);
@@ -3038,6 +2998,7 @@ close_pb(PG_FUNCTION_ARGS)
Datum
close_sl(PG_FUNCTION_ARGS)
{
+#ifdef NOT_USED
LSEG *lseg = PG_GETARG_LSEG_P(0);
LINE *line = PG_GETARG_LINE_P(1);
Point *result;
@@ -3056,6 +3017,13 @@ close_sl(PG_FUNCTION_ARGS)
result = point_copy(&lseg->p[1]);
PG_RETURN_POINT_P(result);
+#endif
+
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("function \"close_sl\" not implemented")));
+
+ PG_RETURN_NULL();
}
/* close_ls()
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index e3822fa..2081312 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -393,10 +393,9 @@ DESCR("geometric polygon '(pt1,...)'");
#define POLYGONOID 604
DATA(insert OID = 628 ( line PGNSP PGUID 32 f b G f t \054 0 701 629 line_in line_out line_recv line_send - - - d p f 0 -1 0 0 _null_ _null_ _null_ ));
-DESCR("geometric line (not implemented)");
+DESCR("geometric line");
#define LINEOID 628
DATA(insert OID = 629 ( _line PGNSP PGUID -1 f b A f t \054 0 628 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ ));
-DESCR("");
/* OIDS 700 - 799 */
diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h
index 5c83a71..1e648c0 100644
--- a/src/include/utils/geo_decls.h
+++ b/src/include/utils/geo_decls.h
@@ -88,19 +88,12 @@ typedef struct
/*---------------------------------------------------------------------
* LINE - Specified by its general equation (Ax+By+C=0).
- * If there is a y-intercept, it is C, which
- * incidentally gives a freebie point on the line
- * (if B=0, then C is the x-intercept).
- * Slope m is precalculated to save time; if
- * the line is not vertical, m == A.
*-------------------------------------------------------------------*/
typedef struct
{
double A,
B,
C;
-
- double m;
} LINE;
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index 8123725..21ad555 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -146,9 +146,6 @@ SELECT '' AS thirty, p.f1, l.s, p.f1 ## l.s AS closest
(30 rows)
--
--- Lines
---
---
-- Boxes
--
SELECT '' as six, box(f1) AS box FROM CIRCLE_TBL;
diff --git a/src/test/regress/expected/line.out b/src/test/regress/expected/line.out
new file mode 100644
index 0000000..7d222fc
--- /dev/null
+++ b/src/test/regress/expected/line.out
@@ -0,0 +1,271 @@
+--
+-- LINE
+-- Infinite lines
+--
+--DROP TABLE LINE_TBL;
+CREATE TABLE LINE_TBL (s line);
+INSERT INTO LINE_TBL VALUES ('{1,-1,1}');
+INSERT INTO LINE_TBL VALUES ('(0,0),(6,6)');
+INSERT INTO LINE_TBL VALUES ('10,-10 ,-3,-4');
+INSERT INTO LINE_TBL VALUES ('[-1e6,2e2,3e5, -4e1]');
+INSERT INTO LINE_TBL VALUES ('(11,22,33,44)');
+INSERT INTO LINE_TBL VALUES ('[(1,0),(1,0)]');
+ERROR: invalid line specification: must be two distinct points
+LINE 1: INSERT INTO LINE_TBL VALUES ('[(1,0),(1,0)]');
+ ^
+-- horizontal
+INSERT INTO LINE_TBL VALUES ('[(1,3),(2,3)]');
+-- vertical
+INSERT INTO LINE_TBL VALUES ('[(3,1),(3,2)]');
+-- bad values for parser testing
+INSERT INTO LINE_TBL VALUES ('{0,0,1}');
+ERROR: invalid line specification: A and B cannot both be zero
+LINE 1: INSERT INTO LINE_TBL VALUES ('{0,0,1}');
+ ^
+INSERT INTO LINE_TBL VALUES ('(3asdf,2 ,3,4r2)');
+ERROR: invalid input syntax for type line: "(3asdf,2 ,3,4r2)"
+LINE 1: INSERT INTO LINE_TBL VALUES ('(3asdf,2 ,3,4r2)');
+ ^
+INSERT INTO LINE_TBL VALUES ('[1,2,3, 4');
+ERROR: invalid input syntax for type line: "[1,2,3, 4"
+LINE 1: INSERT INTO LINE_TBL VALUES ('[1,2,3, 4');
+ ^
+INSERT INTO LINE_TBL VALUES ('[(,2),(3,4)]');
+ERROR: invalid input syntax for type line: "[(,2),(3,4)]"
+LINE 1: INSERT INTO LINE_TBL VALUES ('[(,2),(3,4)]');
+ ^
+INSERT INTO LINE_TBL VALUES ('[(1,2),(3,4)');
+ERROR: invalid input syntax for type line: "[(1,2),(3,4)"
+LINE 1: INSERT INTO LINE_TBL VALUES ('[(1,2),(3,4)');
+ ^
+select * from LINE_TBL;
+ s
+---------------------------------------------
+ {1,-1,1}
+ {1,-1,0}
+ {-0.461538461538462,-1,-5.38461538461538}
+ {-0.000184615384615385,-1,15.3846153846154}
+ {1,-1,11}
+ {0,-1,3}
+ {-1,0,3}
+(7 rows)
+
+-- functions and operators
+SELECT * FROM LINE_TBL WHERE (s <-> line '[(1,2),(3,4)]') < 10;
+ s
+---------------------------------------------
+ {1,-1,1}
+ {1,-1,0}
+ {-0.461538461538462,-1,-5.38461538461538}
+ {-0.000184615384615385,-1,15.3846153846154}
+ {1,-1,11}
+ {0,-1,3}
+ {-1,0,3}
+(7 rows)
+
+SELECT * FROM LINE_TBL WHERE (point '(0.1,0.1)' <-> s) < 1;
+ s
+----------
+ {1,-1,1}
+ {1,-1,0}
+(2 rows)
+
+SELECT * FROM LINE_TBL WHERE (lseg '[(0.1,0.1),(0.2,0.2)]' <-> s) < 1;
+ s
+----------
+ {1,-1,1}
+ {1,-1,0}
+(2 rows)
+
+SELECT line '[(1,1),(2,1)]' <-> line '[(-1,-1),(-2,-1)]';
+ ?column?
+----------
+ 2
+(1 row)
+
+SELECT lseg '[(1,1),(2,1)]' <-> line '[(-1,-1),(-2,-1)]';
+ ?column?
+----------
+ 2
+(1 row)
+
+SELECT point '(-1,1)' <-> line '[(-3,0),(-4,0)]';
+ ?column?
+----------
+ 1
+(1 row)
+
+SELECT lseg '[(1,1),(5,5)]' ?# line '[(2,0),(0,2)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT lseg '[(1,1),(5,5)]' ?# line '[(0,0),(1,0)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ?# box '(0,0,2,2)'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT line '[(3,0),(4,1)]' ?# box '(0,0,2,2)'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT point '(1,1)' <@ line '[(0,0),(2,2)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT point '(1,1)' <@ line '[(0,0),(1,0)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT point '(1,1)' @ line '[(0,0),(2,2)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT point '(1,1)' @ line '[(0,0),(1,0)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT lseg '[(1,1),(2,2)]' <@ line '[(0,0),(2,2)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT lseg '[(1,1),(2,1)]' <@ line '[(0,0),(1,0)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT lseg '[(1,1),(2,2)]' @ line '[(0,0),(2,2)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT lseg '[(1,1),(2,1)]' @ line '[(0,0),(1,0)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT point '(0,1)' ## line '[(0,0),(1,1)]';
+ ?column?
+-----------
+ (0.5,0.5)
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ## lseg '[(1,0),(2,0)]';
+ ?column?
+----------
+ (1,0)
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ?# line '[(1,0),(2,1)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ?# line '[(1,0),(1,1)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' # line '[(1,0),(2,1)]';
+ ?column?
+----------
+
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' # line '[(1,0),(1,1)]';
+ ?column?
+----------
+ (1,1)
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ?|| line '[(1,0),(2,1)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ?|| line '[(1,0),(1,1)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT line '[(0,0),(1,0)]' ?-| line '[(0,0),(0,1)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT line '[(0,0),(1,1)]' ?-| line '[(1,0),(1,1)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT ?- line '[(0,0),(1,0)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT ?- line '[(0,0),(1,1)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT ?| line '[(0,0),(0,1)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT ?| line '[(0,0),(1,1)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT line(point '(1,2)', point '(3,4)');
+ line
+----------
+ {1,-1,1}
+(1 row)
+
+SELECT line '[(1,2),(3,4)]' = line '[(3,4),(4,5)]'; -- true
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT line '[(1,2),(3,4)]' = line '[(3,4),(4,4)]'; -- false
+ ?column?
+----------
+ f
+(1 row)
+
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index 432d39a..cee35af 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -64,6 +64,7 @@ SELECT relname, relhasindex
interval_tbl | f
iportaltest | f
kd_point_tbl | t
+ line_tbl | f
log_table | f
lseg_tbl | f
main_table | f
@@ -166,7 +167,7 @@ SELECT relname, relhasindex
timetz_tbl | f
tinterval_tbl | f
varchar_tbl | f
-(155 rows)
+(156 rows)
--
-- another sanity check: every system catalog that has OIDs should have
diff --git a/src/test/regress/output/misc.source b/src/test/regress/output/misc.source
index 29cbb22..e194f7e 100644
--- a/src/test/regress/output/misc.source
+++ b/src/test/regress/output/misc.source
@@ -638,6 +638,7 @@ SELECT user_relns() AS user_relns
interval_tbl
iportaltest
kd_point_tbl
+ line_tbl
log_table
lseg_tbl
main_table
@@ -696,7 +697,7 @@ SELECT user_relns() AS user_relns
tvvmv
varchar_tbl
xacttest
-(118 rows)
+(119 rows)
SELECT name(equipment(hobby_construct(text 'skywalking', text 'mer')));
name
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index fd08e8d..1c1491c 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -23,7 +23,7 @@ test: numerology
# ----------
# The second group of parallel tests
# ----------
-test: point lseg box path polygon circle date time timetz timestamp timestamptz interval abstime reltime tinterval inet macaddr tstypes comments
+test: point lseg line box path polygon circle date time timetz timestamp timestamptz interval abstime reltime tinterval inet macaddr tstypes comments
# ----------
# Another group of parallel tests
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index 1ed059b..c4d451a 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -23,6 +23,7 @@ test: strings
test: numerology
test: point
test: lseg
+test: line
test: box
test: path
test: polygon
diff --git a/src/test/regress/sql/geometry.sql b/src/test/regress/sql/geometry.sql
index 73f8032..af7f8a5 100644
--- a/src/test/regress/sql/geometry.sql
+++ b/src/test/regress/sql/geometry.sql
@@ -59,10 +59,6 @@
FROM LSEG_TBL l, POINT_TBL p;
--
--- Lines
---
-
---
-- Boxes
--
diff --git a/src/test/regress/sql/line.sql b/src/test/regress/sql/line.sql
new file mode 100644
index 0000000..cd9280b
--- /dev/null
+++ b/src/test/regress/sql/line.sql
@@ -0,0 +1,87 @@
+--
+-- LINE
+-- Infinite lines
+--
+
+--DROP TABLE LINE_TBL;
+CREATE TABLE LINE_TBL (s line);
+
+INSERT INTO LINE_TBL VALUES ('{1,-1,1}');
+INSERT INTO LINE_TBL VALUES ('(0,0),(6,6)');
+INSERT INTO LINE_TBL VALUES ('10,-10 ,-3,-4');
+INSERT INTO LINE_TBL VALUES ('[-1e6,2e2,3e5, -4e1]');
+INSERT INTO LINE_TBL VALUES ('(11,22,33,44)');
+
+INSERT INTO LINE_TBL VALUES ('[(1,0),(1,0)]');
+
+-- horizontal
+INSERT INTO LINE_TBL VALUES ('[(1,3),(2,3)]');
+-- vertical
+INSERT INTO LINE_TBL VALUES ('[(3,1),(3,2)]');
+
+-- bad values for parser testing
+INSERT INTO LINE_TBL VALUES ('{0,0,1}');
+INSERT INTO LINE_TBL VALUES ('(3asdf,2 ,3,4r2)');
+INSERT INTO LINE_TBL VALUES ('[1,2,3, 4');
+INSERT INTO LINE_TBL VALUES ('[(,2),(3,4)]');
+INSERT INTO LINE_TBL VALUES ('[(1,2),(3,4)');
+
+select * from LINE_TBL;
+
+
+-- functions and operators
+
+SELECT * FROM LINE_TBL WHERE (s <-> line '[(1,2),(3,4)]') < 10;
+
+SELECT * FROM LINE_TBL WHERE (point '(0.1,0.1)' <-> s) < 1;
+
+SELECT * FROM LINE_TBL WHERE (lseg '[(0.1,0.1),(0.2,0.2)]' <-> s) < 1;
+
+SELECT line '[(1,1),(2,1)]' <-> line '[(-1,-1),(-2,-1)]';
+SELECT lseg '[(1,1),(2,1)]' <-> line '[(-1,-1),(-2,-1)]';
+SELECT point '(-1,1)' <-> line '[(-3,0),(-4,0)]';
+
+SELECT lseg '[(1,1),(5,5)]' ?# line '[(2,0),(0,2)]'; -- true
+SELECT lseg '[(1,1),(5,5)]' ?# line '[(0,0),(1,0)]'; -- false
+
+SELECT line '[(0,0),(1,1)]' ?# box '(0,0,2,2)'; -- true
+SELECT line '[(3,0),(4,1)]' ?# box '(0,0,2,2)'; -- false
+
+SELECT point '(1,1)' <@ line '[(0,0),(2,2)]'; -- true
+SELECT point '(1,1)' <@ line '[(0,0),(1,0)]'; -- false
+
+SELECT point '(1,1)' @ line '[(0,0),(2,2)]'; -- true
+SELECT point '(1,1)' @ line '[(0,0),(1,0)]'; -- false
+
+SELECT lseg '[(1,1),(2,2)]' <@ line '[(0,0),(2,2)]'; -- true
+SELECT lseg '[(1,1),(2,1)]' <@ line '[(0,0),(1,0)]'; -- false
+
+SELECT lseg '[(1,1),(2,2)]' @ line '[(0,0),(2,2)]'; -- true
+SELECT lseg '[(1,1),(2,1)]' @ line '[(0,0),(1,0)]'; -- false
+
+SELECT point '(0,1)' ## line '[(0,0),(1,1)]';
+
+SELECT line '[(0,0),(1,1)]' ## lseg '[(1,0),(2,0)]';
+
+SELECT line '[(0,0),(1,1)]' ?# line '[(1,0),(2,1)]'; -- false
+SELECT line '[(0,0),(1,1)]' ?# line '[(1,0),(1,1)]'; -- true
+
+SELECT line '[(0,0),(1,1)]' # line '[(1,0),(2,1)]';
+SELECT line '[(0,0),(1,1)]' # line '[(1,0),(1,1)]';
+
+SELECT line '[(0,0),(1,1)]' ?|| line '[(1,0),(2,1)]'; -- true
+SELECT line '[(0,0),(1,1)]' ?|| line '[(1,0),(1,1)]'; -- false
+
+SELECT line '[(0,0),(1,0)]' ?-| line '[(0,0),(0,1)]'; -- true
+SELECT line '[(0,0),(1,1)]' ?-| line '[(1,0),(1,1)]'; -- false
+
+SELECT ?- line '[(0,0),(1,0)]'; -- true
+SELECT ?- line '[(0,0),(1,1)]'; -- false
+
+SELECT ?| line '[(0,0),(0,1)]'; -- true
+SELECT ?| line '[(0,0),(1,1)]'; -- false
+
+SELECT line(point '(1,2)', point '(3,4)');
+
+SELECT line '[(1,2),(3,4)]' = line '[(3,4),(4,5)]'; -- true
+SELECT line '[(1,2),(3,4)]' = line '[(3,4),(4,4)]'; -- false
--
1.8.4.rc3
On Wed, Oct 9, 2013 at 10:44 AM, Peter Eisentraut <peter_e@gmx.net> wrote:
On Thu, 2013-10-03 at 17:50 +0530, Jeevan Chalke wrote:
Will you please attach new patch with above block removed ? Then I
will quickly check that new patch and mark as "Ready For Committer".Here you go.
Thanks Peter. Patch looks good to me and ready to go in now.
Marking as "Ready For Committer".
--
Jeevan B Chalke
Principal Software Engineer, Product Development
EnterpriseDB Corporation