---

slug: /spatial-data-format
---

# Spatial data formats

seekdb supports two standard spatial data formats for representing geometric objects in queries:

* Well-Known Text (WKT)

* Well-Known Binary (WKB)

## WKT

WKT is defined based on Extended Backus-Naur Form (EBNF). WKT can be used both as a data format (referred to as WKT-Data in this document) and for defining spatial reference systems (SRS) in Geographic Information System (GIS) (referred to as WKT-SRS in this document).

### Point

A point does not use commas as separators. Example format:

```sql
POINT(15 20)
```

The following example uses `ST_X()` to extract the `X` coordinate from a point object. The first example directly generates the object using the `Point()` function. The second example uses the WKT representation converted to point through `ST_GeomFromText()`.

```sql
obclient> SELECT ST_X(Point(15, 20));
+---------------------+
| ST_X(Point(15, 20)) |
+---------------------+
|                  15 |
+---------------------+
1 row in set

obclient> SELECT ST_X(ST_GeomFromText('POINT(15 20)'));
+---------------------------------------+
| ST_X(ST_GeomFromText('POINT(15 20)')) |
+---------------------------------------+
|                                    15 |
+---------------------------------------+
1 row in set
```

### Line

A line consists of multiple points separated by commas. Example format:

```sql
LINESTRING(0 0, 10 10, 20 25, 50 60)
```

### Polygon

A polygon consists of at least one exterior ring (closed line) and any number (can be 0) of interior rings (closed lines). Example format:

```sql
POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))
```

### MultiPoint

A MultiPoint consists of multiple points, similar to a line but with different semantics. Multiple connected points form a line, while discrete multiple points form a MultiPoint. Example format:

```sql
MULTIPOINT(0 0, 20 20, 60 60)
```

In the functions `ST_MPointFromText()` and `ST_GeoFromText()`, it is also valid to enclose points in a MultiPoint with parentheses. Example format:

```sql
ST_MPointFromText('MULTIPOINT (1 1, 2 2, 3 3)')
ST_MPointFromText('MULTIPOINT ((1 1), (2 2), (3 3))')
```

### MultiLineString

A MultiLineString is a collection of multiple lines. Example format:

```sql
MULTILINESTRING((10 10, 20 20), (15 15, 30 15))
```

### MultiPolygon

A MultiPolygon is a collection of multiple polygons. Example format:

```sql
MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)),((5 5,7 5,7 7,5 7, 5 5)))
```

### GeometryCollection

A GeometryCollection can be a collection of multiple basic types and collection types.

```sql
GEOMETRYCOLLECTION(POINT(10 10), POINT(30 30), LINESTRING(15 15, 20 20))
```

## WKB

WKB is developed based on the OpenGIS specification and supports seven types (Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, and Geometrycollection) with corresponding format definitions.

### Point

Using `POINT(1 -1)` as an example, the format definition is shown in the following table.

| **Component** | **Specification** | **Type** | **Value** |
| --- | --- | --- | --- |
| **Byte order** | 1 byte | unsigned int | 01 |
| **WKB type** | 4 bytes | unsigned int | 01000000 |
| **X coordinate** | 8 bytes | double-precision | 000000000000F03F |
| **Y coordinate** | 8 bytes | double-precision | 000000000000F0BF |

### Linestring

Using `LINESTRING(1 -1, -1 1)` as an example, the format definition is shown in the following table. `Num points` must be greater than or equal to 2.

| **Component** | **Specification** | **Type** | **Value** |
| --- | --- | --- | --- |
| **Byte order** | 1 byte | unsigned int | 01 |
| **WKB type** | 4 bytes | unsigned int | 02000000 |
| **Num points** | 4 bytes | unsigned int | 02000000 |
| **X coordinate** | 8 bytes | double-precision | 000000000000F03F |
| **Y coordinate** | 8 bytes | double-precision | 000000000000F0BF |
| **X coordinate** | 8 bytes | double-precision | 000000000000F0BF |
| **Y coordinate** | 8 bytes | double-precision | 000000000000F03F |

### Polygon

| **Component** | **Specification** | **Type** | **Value** |
| --- | --- | --- | --- |
| **Byte order** | 1 byte | unsigned int | 01 |
| **WKB type** | 4 bytes | unsigned int | 03000000 |
| **Num rings** | 4 bytes | unsigned int | Greater than or equal to 1 |
| **repeat ring** | - |- | - |

### MultiPoint

| **Component** | **Specification** | **Type** | **Value** |
| --- | --- | --- | --- |
| **Byte order** | 1 byte | unsigned int | 01 |
| **WKB type** | 4 bytes | unsigned int | 04000000 |
| **Num points** | 4 bytes | unsigned int | Num points >= 1 |
| **repeat POINT** | - |-  | - |

### MultiLineString

| **Component** | **Specification** | **Type** | **Value** |
| --- | --- | --- | --- |
| **Byte order** | 1 byte | unsigned int | 01 |
| **WKB type** | 4 bytes | unsigned int | 05000000 |
| **Num linestrings** | 4 bytes | unsigned int | Greater than or equal to 1 |
| **repeat LINESTRING** | - | - | - |

### MultiPolygon

| **Component** | **Specification** | **Type** | **Value** |
| --- | --- | --- | --- |
| **Byte order** | 1 byte | unsigned int | 01 |
| **WKB type** | 4 bytes | unsigned int | 06000000 |
| **Num polygons** | 4 bytes | unsigned int | Greater than or equal to 1 |
| **repeat POLYGON** | - | - | - |

### GeometryCollection

| **Component** | **Specification** | **Type** | **Value** |
| --- | --- | --- | --- |
| **Byte order** | 1 byte | unsigned int | 01 |
| **WKB type** | 4 bytes | unsigned int | 07000000 |
| **Num wkbs** | 4 bytes | unsigned int | - |
| **repeat WKB** | - | - | - |

>Note:
>
>* Only GeometryCollection can be empty, indicating that 0 elements are stored. All other types cannot be empty.
>* When `LENGTH()` is applied to a GIS object, it returns the length of the stored binary data.

```sql
obclient [test]> SET @g = ST_GeomFromText('POINT(1 -1)');
Query OK, 0 rows affected

obclient [test]> SELECT LENGTH(@g);
+------------+
| LENGTH(@g) |
+------------+
|         25 |
+------------+
1 row in set

obclient [test]> SELECT HEX(@g);
+----------------------------------------------------+
| HEX(@g)                                            |
+----------------------------------------------------+
| 000000000101000000000000000000F03F000000000000F0BF |
+----------------------------------------------------+
1 row in set
```

## Syntax and geometric validity

### Syntax validity

Syntax validity must satisfy the following conditions:

- A linestring must have at least two points.
- A polygon must have at least one ring.
- A polygon must be closed (the first and last points are the same).
- A polygon's ring must have at least four points (the smallest polygon is a triangle, where the first and last points are the same).
- Except for GeometryCollection, other collection types cannot be empty.

### Geometric validity

Geometric validity must satisfy the following conditions:

- A polygon cannot intersect with itself.
- The exterior ring of a Polygon must be outside the interior rings.
- Multipolygons cannot contain overlapping polygons.

You can explicitly check the geometric validity of a geometry object using the ST_IsValid() function.

## GIS Examples

### Insert data

```sql
// Both conversion functions and WKT are included in the SQL statement.
INSERT INTO geom VALUES (ST_GeomFromText('POINT(1 1)'));

// WKT is provided as a parameter.
SET @g = 'POINT(1 1)';
INSERT INTO geom VALUES (ST_GeomFromText(@g));

// Conversion expressions are directly embedded in the parameters.
SET @g = ST_GeomFromText('POINT(1 1)');
INSERT INTO geom VALUES (@g);

// A unified conversion function is used.
SET @g = 'LINESTRING(0 0,1 1,2 2)';
INSERT INTO geom VALUES (ST_GeomFromText(@g));

SET @g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))';
INSERT INTO geom VALUES (ST_GeomFromText(@g));

SET @g ='GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))';
INSERT INTO geom VALUES (ST_GeomFromText(@g));

// Type-specific conversion functions are employed.
SET @g = 'POINT(1 1)';
INSERT INTO geom VALUES (ST_PointFromText(@g));

SET @g = 'LINESTRING(0 0,1 1,2 2)';
INSERT INTO geom VALUES (ST_LineStringFromText(@g));

SET @g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))';
INSERT INTO geom VALUES (ST_PolygonFromText(@g));

SET @g =
'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))';
INSERT INTO geom VALUES (ST_GeomCollFromText(@g));

// Data can also be inserted directly using WKB.
INSERT INTO geom VALUES(ST_GeomFromWKB(X'0101000000000000000000F03F000000000000F03F'));
```

### Query data

```sql
// Query data and convert it to WKT format for output.
SELECT ST_AsText(g) FROM geom;

// Query data and convert it to WKB format for output.
SELECT ST_AsBinary(g) FROM geom;
```