lib/mosql/schema.rb in mosql-0.3.1 vs lib/mosql/schema.rb in mosql-0.3.2
- old
+ new
@@ -3,31 +3,35 @@
class Schema
include MoSQL::Logging
def to_array(lst)
- array = []
- lst.each do |ent|
+ lst.map do |ent|
+ col = nil
if ent.is_a?(Hash) && ent[:source].is_a?(String) && ent[:type].is_a?(String)
# new configuration format
- array << {
+ col = {
:source => ent.fetch(:source),
:type => ent.fetch(:type),
:name => (ent.keys - [:source, :type]).first,
}
elsif ent.is_a?(Hash) && ent.keys.length == 1 && ent.values.first.is_a?(String)
- array << {
+ col = {
:source => ent.first.first,
:name => ent.first.first,
:type => ent.first.last
}
else
raise SchemaError.new("Invalid ordered hash entry #{ent.inspect}")
end
+ if !col.key?(:array_type) && /\A(.+)\s+array\z/i.match(col[:type])
+ col[:array_type] = $1
+ end
+
+ col
end
- array
end
def check_columns!(ns, spec)
seen = Set.new
spec[:columns].each do |col|
@@ -85,11 +89,17 @@
if col[:source].to_sym == :_id
primary_key [col[:name].to_sym]
end
end
if meta[:extra_props]
- column '_extra_props', 'TEXT'
+ type =
+ if meta[:extra_props] == "JSON"
+ "JSON"
+ else
+ "TEXT"
+ end
+ column '_extra_props', type
end
end
end
end
end
@@ -102,11 +112,11 @@
end
@map[db]
end
def find_ns(ns)
- db, collection = ns.split(".")
+ db, collection = ns.split(".", 2)
unless spec = find_db(db)
return nil
end
unless schema = spec[collection]
log.debug("No mapping for ns: #{ns}")
@@ -164,36 +174,52 @@
else
v = fetch_and_delete_dotted(obj, source)
case v
when BSON::Binary, BSON::ObjectId, Symbol
v = v.to_s
- when Hash, Array
+ when BSON::DBRef
+ v = v.object_id.to_s
+ when Hash
v = JSON.dump(v)
+ when Array
+ if col[:array_type]
+ v = Sequel.pg_array(v, col[:array_type])
+ else
+ v = JSON.dump(v)
+ end
end
end
row << v
end
if schema[:meta][:extra_props]
- # Kludgily delete binary blobs from _extra_props -- they may
- # contain invalid UTF-8, which to_json will not properly encode.
- extra = {}
- obj.each do |k,v|
- case v
- when BSON::Binary
- next
- when Float
- # NaN is illegal in JSON. Translate into null.
- v = nil if v.nan?
- end
- extra[k] = v
- end
+ extra = sanitize(obj)
row << JSON.dump(extra)
end
log.debug { "Transformed: #{row.inspect}" }
row
+ end
+
+ def sanitize(value)
+ # Base64-encode binary blobs from _extra_props -- they may
+ # contain invalid UTF-8, which to_json will not properly encode.
+ case value
+ when Hash
+ ret = {}
+ value.each {|k, v| ret[k] = sanitize(v)}
+ ret
+ when Array
+ value.map {|v| sanitize(v)}
+ when BSON::Binary
+ Base64.encode64(value.to_s)
+ when Float
+ # NaN is illegal in JSON. Translate into null.
+ value.nan? ? nil : value
+ else
+ value
+ end
end
def copy_column?(col)
col[:source] != '$timestamp'
end