[PATCH] Revive line type

Lists: pgsql-hackers
From: Peter Eisentraut <peter_e(at)gmx(dot)net>
To: pgsql-hackers(at)postgresql(dot)org
Subject: line type
Date: 2012-10-12 05:38:24
Message-ID: 1350020304.2028.3.camel@vanquo.pezone.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

What's the deal with the line type?

It's installed in the catalogs and listed in the documentation,
varyingly as not implemented or not fully implemented, but all the
support functions throw an error. Is there any known list of things
that would need to be done to make it fully implemented? Or should we
just get rid of it?


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Peter Eisentraut <peter_e(at)gmx(dot)net>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: line type
Date: 2012-10-12 15:28:01
Message-ID: 23562.1350055681@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Peter Eisentraut <peter_e(at)gmx(dot)net> writes:
> What's the deal with the line type?
> It's installed in the catalogs and listed in the documentation,
> varyingly as not implemented or not fully implemented, but all the
> support functions throw an error. Is there any known list of things
> that would need to be done to make it fully implemented? Or should we
> just get rid of it?

Tom Lockhart seems to have lobotomized line_in and line_out in commit
402b47cffafcbbc66af8ee6b6340b4db09f00a7b. A look in the archives
suggests it was because of my complaint the day before:
http://archives.postgresql.org/pgsql-hackers/1998-08/msg00346.php

I'm not sure there's anything wrong with line_in, but line_out is still
obviously broken. However, there are a couple dozen other functions
taking/returning "line", and in general those don't look significantly
more bogus than any other part of geo_ops.c.

I do notice this comment above line_in:

** 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.

but that argument seems specious from here. Even if it's mostly a
support type, being able to get at it would be useful for
testing/debugging the other operations, I think.

I'd vote for fixing the I/O functions and adding some docs and
regression tests ... but on the other hand, I'm not volunteering
to do the work.

regards, tom lane


From: Peter Eisentraut <peter_e(at)gmx(dot)net>
To: pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: [PATCH] Revive line type
Date: 2013-06-15 00:30:51
Message-ID: 1371256251.13762.3.camel@vanquo.pezone.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

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.
---
This just revives existing functionality, doesn't add anything new.
One thing that the original code did not settle was how to convert a
line in form Ax+By+C=0 to the two-points output form. Obviously, you
can just pick to random points on the line, but I wonder whether there
is a more standard solution.

doc/src/sgml/datatype.sgml | 34 +++-
doc/src/sgml/func.sgml | 6 +
src/backend/utils/adt/geo_ops.c | 108 +++++--------
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 | 243 ++++++++++++++++++++++++++++
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 | 77 +++++++++
13 files changed, 408 insertions(+), 86 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 4c5af4b..835a189 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..61a1900 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));
}

@@ -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..39b912a
--- /dev/null
+++ b/src/test/regress/expected/line.out
@@ -0,0 +1,243 @@
+--
+-- 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)]');
+ ^
+-- 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)]
+(5 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)]
+(5 rows)
+
+SELECT * FROM LINE_TBL WHERE (point '(0.1,0.1)' <-> s) < 1;
+ s
+-----------------------------------------------
+ [(0,1),(1,2)]
+ [(0,0),(1,1)]
+ [(0,-5.38461538461538),(1,-5.84615384615385)]
+(3 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)]
+ [(0,-5.38461538461538),(1,-5.84615384615385)]
+(3 rows)
+
+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..25e680d
--- /dev/null
+++ b/src/test/regress/sql/line.sql
@@ -0,0 +1,77 @@
+--
+-- 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)]');
+
+-- 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 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


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Peter Eisentraut <peter_e(at)gmx(dot)net>
Cc: pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: [PATCH] Revive line type
Date: 2013-06-15 15:02:02
Message-ID: 6899.1371308522@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Peter Eisentraut <peter_e(at)gmx(dot)net> writes:
> 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.
> ---
> This just revives existing functionality, doesn't add anything new.
> One thing that the original code did not settle was how to convert a
> line in form Ax+By+C=0 to the two-points output form. Obviously, you
> can just pick to random points on the line, but I wonder whether there
> is a more standard solution.

ISTM printing a line as two points is an unfortunate representational
choice altogether. If the internal form is Ax+By+C=0, shouldn't the
text form expose A,B,C directly? What you've got here necessarily
suffers a lot of roundoff error during I/O conversions, and so it seems
pretty likely to fail dump-and-reload tests.

regards, tom lane