Skip to content

Commit 4d97e7f

Browse files
authored
Make geo optional (#90)
1 parent 25c85a0 commit 4d97e7f

File tree

3 files changed

+52
-22
lines changed

3 files changed

+52
-22
lines changed

README.md

+20-6
Original file line numberDiff line numberDiff line change
@@ -113,15 +113,13 @@ point, polygon, ... %Geo.Point{coordinates: {0.0, 1.0}}, ... *****
113113
\*\*\*\* MySQL added a native JSON type in version 5.7.8, if you're using earlier versions,
114114
remember to use TEXT column for your JSON field.
115115

116-
\*\*\*\*\* Encoding/decoding between `Geo.*` structs and the OpenGIS WKB binary format is
117-
done using the [Geo](https://github.com/bryanjos/geo) package. If you're using MyXQL geometry
118-
types with Ecto and need to for example accept a WKT format as user input, consider implementing an
119-
[custom Ecto type](https://hexdocs.pm/ecto/Ecto.Type.html). Note, some structs like `%Geo.PointZ{}`
120-
does not have equivalent on the MySQL server side and thus shouldn't be used.
116+
\*\*\*\*\* See "Geometry support" section below
121117

122118
## JSON support
123119

124-
MyXQL comes with JSON support out of the box via the [Jason](https://github.com/michalmuskala/jason) library. To use it, add `:jason` to your dependencies:
120+
MyXQL comes with JSON support via the [Jason](https://github.com/michalmuskala/jason) library.
121+
122+
To use it, add `:jason` to your dependencies:
125123

126124
```elixir
127125
{:jason, "~> 1.0"}
@@ -133,6 +131,22 @@ You can customize it to use another library via the `:json_library` configuratio
133131
config :myxql, :json_library, SomeJSONModule
134132
```
135133

134+
## Geometry support
135+
136+
MyXQL comes with Geometry types support via the [Geo](https://github.com/bryanjos/geo) package.
137+
138+
To use it, add `:geo` to your dependencies:
139+
140+
```elixir
141+
{:geo, "~> 3.3"}
142+
```
143+
144+
Note, some structs like `%Geo.PointZ{}` does not have equivalent on the MySQL server side and thus
145+
shouldn't be used.
146+
147+
If you're using MyXQL geometry types with Ecto and need to for example accept a WKT format as user
148+
input, consider implementing an [custom Ecto type](https://hexdocs.pm/ecto/Ecto.Type.html).
149+
136150
## Contributing
137151

138152
Run tests:

lib/myxql/protocol/values.ex

+31-15
Original file line numberDiff line numberDiff line change
@@ -223,13 +223,15 @@ defmodule MyXQL.Protocol.Values do
223223
{:mysql_type_tiny, <<0>>}
224224
end
225225

226-
def encode_binary_value(%Geo.Point{} = geo), do: encode_geometry(geo)
227-
def encode_binary_value(%Geo.MultiPoint{} = geo), do: encode_geometry(geo)
228-
def encode_binary_value(%Geo.LineString{} = geo), do: encode_geometry(geo)
229-
def encode_binary_value(%Geo.MultiLineString{} = geo), do: encode_geometry(geo)
230-
def encode_binary_value(%Geo.Polygon{} = geo), do: encode_geometry(geo)
231-
def encode_binary_value(%Geo.MultiPolygon{} = geo), do: encode_geometry(geo)
232-
def encode_binary_value(%Geo.GeometryCollection{} = geo), do: encode_geometry(geo)
226+
if Code.ensure_loaded?(Geo) do
227+
def encode_binary_value(%Geo.Point{} = geo), do: encode_geometry(geo)
228+
def encode_binary_value(%Geo.MultiPoint{} = geo), do: encode_geometry(geo)
229+
def encode_binary_value(%Geo.LineString{} = geo), do: encode_geometry(geo)
230+
def encode_binary_value(%Geo.MultiLineString{} = geo), do: encode_geometry(geo)
231+
def encode_binary_value(%Geo.Polygon{} = geo), do: encode_geometry(geo)
232+
def encode_binary_value(%Geo.MultiPolygon{} = geo), do: encode_geometry(geo)
233+
def encode_binary_value(%Geo.GeometryCollection{} = geo), do: encode_geometry(geo)
234+
end
233235

234236
def encode_binary_value(term) when is_list(term) or is_map(term) do
235237
string = json_library().encode!(term)
@@ -240,10 +242,12 @@ defmodule MyXQL.Protocol.Values do
240242
raise ArgumentError, "query has invalid parameter #{inspect(other)}"
241243
end
242244

243-
defp encode_geometry(geo) do
244-
srid = geo.srid || 0
245-
binary = %{geo | srid: nil} |> Geo.WKB.encode!(:ndr) |> Base.decode16!()
246-
{:mysql_type_geometry, encode_string_lenenc(<<srid::uint4, binary::binary>>)}
245+
if Code.ensure_loaded?(Geo) do
246+
defp encode_geometry(geo) do
247+
srid = geo.srid || 0
248+
binary = %{geo | srid: nil} |> Geo.WKB.encode!(:ndr) |> Base.decode16!()
249+
{:mysql_type_geometry, encode_string_lenenc(<<srid::uint4, binary::binary>>)}
250+
end
247251
end
248252

249253
## Time/DateTime
@@ -389,10 +393,22 @@ defmodule MyXQL.Protocol.Values do
389393
Enum.reverse(acc)
390394
end
391395

392-
# https://dev.mysql.com/doc/refman/8.0/en/gis-data-formats.html#gis-internal-format
393-
defp decode_geometry(<<srid::uint4, r::bits>>) do
394-
srid = if srid == 0, do: nil, else: srid
395-
r |> Base.encode16() |> Geo.WKB.decode!() |> Map.put(:srid, srid)
396+
if Code.ensure_loaded?(Geo) do
397+
# https://dev.mysql.com/doc/refman/8.0/en/gis-data-formats.html#gis-internal-format
398+
defp decode_geometry(<<srid::uint4, r::bits>>) do
399+
srid = if srid == 0, do: nil, else: srid
400+
r |> Base.encode16() |> Geo.WKB.decode!() |> Map.put(:srid, srid)
401+
end
402+
else
403+
defp decode_geometry(_) do
404+
raise """
405+
encoding/decoding geometry types requires :geo package, add:
406+
407+
{:geo, "~> 3.3"}
408+
409+
to your mix.exs and run `mix deps.compile --force myxql`.
410+
"""
411+
end
396412
end
397413

398414
defp decode_int1(<<v::int1, r::bits>>, null_bitmap, t, acc),

mix.exs

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ defmodule MyXQL.MixProject do
5151
{:db_connection, "~> 2.0", db_connection_opts()},
5252
{:decimal, "~> 1.6"},
5353
{:jason, "~> 1.0", optional: true},
54-
{:geo, "~> 3.3"},
54+
{:geo, "~> 3.3", optional: true},
5555
{:binpp, ">= 0.0.0", only: [:dev, :test]},
5656
{:dialyxir, "~> 1.0-rc", only: :dev, runtime: false},
5757
{:ex_doc, ">= 0.0.0", only: :dev, runtime: false},

0 commit comments

Comments
 (0)