Revive line type
authorPeter Eisentraut <peter_e@gmx.net>
Wed, 9 Oct 2013 05:09:18 +0000 (01:09 -0400)
committerPeter Eisentraut <peter_e@gmx.net>
Thu, 10 Oct 2013 02:34:38 +0000 (22:34 -0400)
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>
13 files changed:
doc/src/sgml/datatype.sgml
doc/src/sgml/func.sgml
src/backend/utils/adt/geo_ops.c
src/include/catalog/pg_type.h
src/include/utils/geo_decls.h
src/test/regress/expected/geometry.out
src/test/regress/expected/line.out [new file with mode: 0644]
src/test/regress/expected/sanity_check.out
src/test/regress/output/misc.source
src/test/regress/parallel_schedule
src/test/regress/serial_schedule
src/test/regress/sql/geometry.sql
src/test/regress/sql/line.sql [new file with mode: 0644]

index 87668ea0c1c9f41872cc9fdf318baf16d361145c..07f0385d80d4eeb4f568e43efbf387f4791a3a56 100644 (file)
@@ -3051,9 +3051,7 @@ SELECT person.name, holidays.num_weeks FROM person, holidays
    <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 @@ SELECT person.name, holidays.num_weeks FROM person, holidays
        <row>
         <entry>Name</entry>
         <entry>Storage Size</entry>
-        <entry>Representation</entry>
         <entry>Description</entry>
+        <entry>Representation</entry>
        </row>
       </thead>
       <tbody>
@@ -3077,8 +3075,8 @@ SELECT person.name, holidays.num_weeks FROM person, holidays
        <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>
@@ -3152,6 +3150,38 @@ SELECT person.name, holidays.num_weeks FROM person, holidays
     </para>
    </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>
 
index c3090dd2b9f0f9d653593b9cf615bf20cea9f487..be7b00b1f323eeaac91f331f75502010f848991a 100644 (file)
@@ -8122,6 +8122,12 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple
         <entry>polygon to circle</entry>
         <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>
index 5d0b59610616aedff45c006bbda14bad24762662..b792d2697724f69351db7e16d3463cbc62c3398c 100644 (file)
@@ -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()
index e3822faf6604b9cf9afa30d906c10501af4270b9..20813125ab22ae349eee5077057aeb3e9556ac0d 100644 (file)
@@ -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 */
 
index 5c83a71e7aae0702c1938eca0ea860d77a301494..1e648c0befcd7c04130427a8c635ca6584eccfac 100644 (file)
@@ -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;
 
 
index 81237252eb77b3c0e09922f019cfbd4fb188d0d5..21ad555c79843230d07306f9ed435c74bf95390b 100644 (file)
@@ -145,9 +145,6 @@ SELECT '' AS thirty, p.f1, l.s, p.f1 ## l.s AS closest
         | (10,10)    | [(11,22),(33,44)]             | (11,22)
 (30 rows)
 
---
--- Lines
---
 --
 -- Boxes
 --
diff --git a/src/test/regress/expected/line.out b/src/test/regress/expected/line.out
new file mode 100644 (file)
index 0000000..7d222fc
--- /dev/null
@@ -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)
+
index 432d39a4911ffaa7107a9011d584b6be1c61c8d7..cee35aff3ab448a41a64f6c584eb124dbbbffee3 100644 (file)
@@ -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
index 29cbb22fb8572a0b5638d7e43b73ea3d784688d4..e194f7ed5cd305351bea56101d2c4bff8af93dbc 100644 (file)
@@ -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 
index fd08e8ddf005c0a4750b57c5a626648335796cdb..1c1491c3f3ee3b23fd04902a5ad6801192233a90 100644 (file)
@@ -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
index 1ed059be6ef10f4635b735f84232a95547846244..c4d451ab00c4c443f8705faea243f0a868340994 100644 (file)
@@ -23,6 +23,7 @@ test: strings
 test: numerology
 test: point
 test: lseg
+test: line
 test: box
 test: path
 test: polygon
index 73f8032bb15a6113d61883ee93f190408cbb22a7..af7f8a51cc7e22309a363df53932871231d17394 100644 (file)
@@ -58,10 +58,6 @@ SELECT '' AS count, p.f1, l.s, l.s # p.f1 AS intersection
 SELECT '' AS thirty, p.f1, l.s, p.f1 ## l.s AS closest
    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 (file)
index 0000000..cd9280b
--- /dev/null
@@ -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