Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions spec/db_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought it would be a type_safe_value why it's not?

end
end

Expand Down
3 changes: 2 additions & 1 deletion src/mysql.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "db"
require "json"
require "./mysql/*"

module MySql
Expand All @@ -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
Expand Down
31 changes: 31 additions & 0 deletions src/mysql/types.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require "json"

# :nodoc:
abstract struct MySql::Type
# Column types
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -315,4 +322,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")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does MySQL sends trailing \u0013 on all json values? Is there a documentation/reference for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems to be a prefix for all the JSON data. I have not been able to find mysql documentation on it however.

JSON.parse(str)
rescue e
nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why exceptions should be swallowed?

end

def self.parse(str : ::String)
JSON.parse(str)
rescue e
nil
end
end
end