diff --git a/spec/db_spec.cr b/spec/db_spec.cr index c059685..9d77eaf 100644 --- a/spec/db_spec.cr +++ b/spec/db_spec.cr @@ -53,6 +53,7 @@ DB::DriverSpecs(MySql::Any).run do sample_value Time.utc(2016, 2, 15, 10, 15, 30, nanosecond: 543_012_000), "timestamp(6)", "TIMESTAMP '2016-02-15 10:15:30.543012'" sample_value Time::Span.new(0, 10, 15, 30, nanoseconds: 543_000_000), "Time(3)", "TIME '10:15:30.543'" sample_value Time::Span.new(0, 10, 15, 30, nanoseconds: 543_012_000), "Time(6)", "TIME '10:15:30.543012'" + sample_value JSON::Any.new({"example" => JSON::Any.new("json")}), "JSON", "'{\"example\": \"json\"}'", type_safe_value: false end end diff --git a/src/mysql.cr b/src/mysql.cr index ceaff6b..e454407 100644 --- a/src/mysql.cr +++ b/src/mysql.cr @@ -1,4 +1,5 @@ require "db" +require "json" require "./mysql/*" module MySql @@ -10,7 +11,7 @@ module MySql end end - alias Any = DB::Any | Int16 | Int8 | Time::Span + alias Any = DB::Any | Int16 | Int8 | Time::Span | JSON::Any # :nodoc: TIME_ZONE = Time::Location::UTC diff --git a/src/mysql/types.cr b/src/mysql/types.cr index 3c0c841..5e0ccb3 100644 --- a/src/mysql/types.cr +++ b/src/mysql/types.cr @@ -1,3 +1,5 @@ +require "json" + # :nodoc: abstract struct MySql::Type # Column types @@ -60,6 +62,10 @@ abstract struct MySql::Type MySql::Type::Null end + def self.type_for(t : ::JSON::Any.class) + MySql::Type::Json + end + def self.type_for(t) raise "MySql::Type does not support #{t} values" end @@ -144,6 +150,7 @@ abstract struct MySql::Type nil end end + decl_type Timestamp, 0x07u8, ::Time do def self.write(packet, v : ::Time) MySql::Type::DateTime.write(packet, v) @@ -351,4 +358,28 @@ abstract struct MySql::Type end end decl_type Geometry, 0xffu8 + + # Parse the JSON column type + decl_type Json, 245_u8, JSON::Any do + def self.write(packet, v : String) + packet.write_lenenc_string v + end + + def self.write(packet, v : ::JSON::Any) + packet.write_lenenc_string v.to_json + end + + def self.read(packet) + str = packet.read_lenenc_string.lchop("\u0013") + JSON.parse(str) + rescue e + nil + end + + def self.parse(str : ::String) + JSON.parse(str) + rescue e + nil + end + end end