sequel 5.20.0 → 5.21.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -52,6 +52,12 @@
52
52
  # DB[:a].server(:read_only).delete # Uses shard2
53
53
  # end
54
54
  #
55
+ # If you use an invalid server when calling with_server, it will be
56
+ # treated the same way as if you called Dataset#server with an invalid
57
+ # server. By default, the default server will be used in such cases.
58
+ # If you would like a different server to be used, or an exception to
59
+ # be raised, then use the :servers_hash Database option.
60
+ #
55
61
  # Related modules: Sequel::ServerBlock, Sequel::UnthreadedServerBlock,
56
62
  # Sequel::ThreadedServerBlock
57
63
 
@@ -110,9 +116,9 @@ module Sequel
110
116
  else
111
117
  case server
112
118
  when :default, nil
113
- @default_servers[-1][0]
119
+ @servers[@default_servers[-1][0]]
114
120
  when :read_only
115
- @default_servers[-1][1]
121
+ @servers[@default_servers[-1][1]]
116
122
  else
117
123
  super
118
124
  end
@@ -155,11 +161,16 @@ module Sequel
155
161
  if !a || a.empty?
156
162
  super
157
163
  else
164
+ # Hash handling required to work when loaded after arbitrary servers plugin.
158
165
  case server
159
166
  when :default, nil
160
- a[-1][0]
167
+ v = a[-1][0]
168
+ v = @servers[v] unless v.is_a?(Hash)
169
+ v
161
170
  when :read_only
162
- a[-1][1]
171
+ v = a[-1][1]
172
+ v = @servers[v] unless v.is_a?(Hash)
173
+ v
163
174
  else
164
175
  super
165
176
  end
@@ -126,6 +126,9 @@ module Sequel
126
126
  a = opts.merge(opts.fetch(:ancestors, OPTS))
127
127
  ancestors = a.fetch(:name, :ancestors)
128
128
  a[:read_only] = true unless a.has_key?(:read_only)
129
+ a[:eager_grapher] = proc do |_|
130
+ raise Sequel::Error, "the #{ancestors} association for #{self} does not support eager graphing"
131
+ end
129
132
  a[:eager_loader_key] = key
130
133
  a[:dataset] ||= proc do
131
134
  base_ds = model.where(prkey_array.zip(key_array.map{|k| get_column_value(k)}))
@@ -221,6 +224,9 @@ module Sequel
221
224
  d = opts.merge(opts.fetch(:descendants, OPTS))
222
225
  descendants = d.fetch(:name, :descendants)
223
226
  d[:read_only] = true unless d.has_key?(:read_only)
227
+ d[:eager_grapher] = proc do |_|
228
+ raise Sequel::Error, "the #{descendants} association for #{self} does not support eager graphing"
229
+ end
224
230
  la = d[:level_alias] ||= :x_level_x
225
231
  d[:dataset] ||= proc do
226
232
  base_ds = model.where(key_array.zip(prkey_array.map{|k| get_column_value(k)}))
@@ -6,7 +6,7 @@ module Sequel
6
6
 
7
7
  # The minor version of Sequel. Bumped for every non-patch level
8
8
  # release, generally around once a month.
9
- MINOR = 20
9
+ MINOR = 21
10
10
 
11
11
  # The tiny version of Sequel. Usually 0, only bumped for bugfix
12
12
  # releases that fix regressions from previous versions.
@@ -40,6 +40,30 @@ describe "A MSSQL database" do
40
40
  end
41
41
  end
42
42
 
43
+ describe "MSSQL decimal locale handling" do
44
+ before do
45
+ @locale = WIN32OLE.locale
46
+ @decimal = BigDecimal('1234.56')
47
+ end
48
+ after do
49
+ WIN32OLE.locale = @locale
50
+ end
51
+
52
+ it "should work with current locale" do
53
+ DB.get(Sequel.cast(@decimal, 'decimal(16,4)').as(:v)).must_equal @decimal
54
+ end
55
+
56
+ it "should work with 1031 locale" do
57
+ WIN32OLE.locale = 1031
58
+ DB.get(Sequel.cast(@decimal, 'decimal(16,4)').as(:v)).must_equal @decimal
59
+ end
60
+
61
+ it "should work with 1033 locale" do
62
+ WIN32OLE.locale = 1033
63
+ DB.get(Sequel.cast(@decimal, 'decimal(16,4)').as(:v)).must_equal @decimal
64
+ end
65
+ end if DB.adapter_scheme == :ado
66
+
43
67
  describe "MSSQL" do
44
68
  before(:all) do
45
69
  @db = DB
@@ -551,11 +551,6 @@ describe "A MySQL database" do
551
551
  db = Sequel.connect(DB.opts.merge(:read_timeout=>22342))
552
552
  db.test_connection
553
553
  end
554
-
555
- it "should accept a connect_timeout option when connecting" do
556
- db = Sequel.connect(DB.opts.merge(:connect_timeout=>22342))
557
- db.test_connection
558
- end
559
554
  end
560
555
 
561
556
  describe "MySQL foreign key support" do
@@ -2944,6 +2944,8 @@ describe 'PostgreSQL json type' do
2944
2944
  @h = {'a'=>'b', '1'=>[3, 4, 5]}
2945
2945
  end
2946
2946
  after do
2947
+ @db.wrap_json_primitives = nil
2948
+ @db.typecast_json_strings = nil
2947
2949
  @db.drop_table?(:items)
2948
2950
  end
2949
2951
 
@@ -2951,9 +2953,12 @@ describe 'PostgreSQL json type' do
2951
2953
  json_types << :jsonb if DB.server_version >= 90400
2952
2954
  json_types.each do |json_type|
2953
2955
  json_array_type = "#{json_type}[]"
2954
- pg_json = lambda{|v| Sequel.send(:"pg_#{json_type}", v)}
2956
+ pg_json = Sequel.method(:"pg_#{json_type}")
2957
+ pg_json_wrap = Sequel.method(:"pg_#{json_type}_wrap")
2955
2958
  hash_class = json_type == :jsonb ? Sequel::Postgres::JSONBHash : Sequel::Postgres::JSONHash
2956
2959
  array_class = json_type == :jsonb ? Sequel::Postgres::JSONBArray : Sequel::Postgres::JSONArray
2960
+ str_class = json_type == :jsonb ? Sequel::Postgres::JSONBString : Sequel::Postgres::JSONString
2961
+ object_class = json_type == :jsonb ? Sequel::Postgres::JSONBObject : Sequel::Postgres::JSONObject
2957
2962
 
2958
2963
  it 'insert and retrieve json values' do
2959
2964
  @db.create_table!(:items){column :j, json_type}
@@ -2983,6 +2988,44 @@ describe 'PostgreSQL json type' do
2983
2988
  @ds.all.must_equal rs
2984
2989
  end
2985
2990
 
2991
+ it 'insert and retrieve json primitive values' do
2992
+ @db.create_table!(:items){column :j, json_type}
2993
+ ['str', 1, 2.5, nil, true, false].each do |rv|
2994
+ @ds.delete
2995
+ @ds.insert(pg_json_wrap.call(rv))
2996
+ @ds.count.must_equal 1
2997
+ rs = @ds.all
2998
+ v = rs.first[:j]
2999
+ v.class.must_equal(rv.class)
3000
+ if rv.nil?
3001
+ v.must_be_nil
3002
+ else
3003
+ v.must_equal rv
3004
+ end
3005
+ end
3006
+
3007
+ @db.wrap_json_primitives = true
3008
+ ['str', 1, 2.5, nil, true, false].each do |rv|
3009
+ @ds.delete
3010
+ @ds.insert(pg_json_wrap.call(rv))
3011
+ @ds.count.must_equal 1
3012
+ rs = @ds.all
3013
+ v = rs.first[:j]
3014
+ v.class.ancestors.must_include(object_class)
3015
+ v.__getobj__.must_be_kind_of(rv.class)
3016
+ if rv.nil?
3017
+ v.must_be_nil
3018
+ v.__getobj__.must_be_nil
3019
+ else
3020
+ v.must_equal rv
3021
+ v.__getobj__.must_equal rv
3022
+ end
3023
+ @ds.delete
3024
+ @ds.insert(rs.first)
3025
+ @ds.all[0][:j].must_equal rs[0][:j]
3026
+ end
3027
+ end
3028
+
2986
3029
  it 'insert and retrieve json[] values' do
2987
3030
  @db.create_table!(:items){column :j, json_array_type}
2988
3031
  j = Sequel.pg_array([pg_json.call('a'=>1), pg_json.call(['b', 2])])
@@ -2999,16 +3042,122 @@ describe 'PostgreSQL json type' do
2999
3042
  @ds.all.must_equal rs
3000
3043
  end
3001
3044
 
3045
+ it 'insert and retrieve json[] values with json primitives' do
3046
+ @db.create_table!(:items){column :j, json_array_type}
3047
+ raw = ['str', 1, 2.5, nil, true, false]
3048
+ j = Sequel.pg_array(raw.map(&pg_json_wrap), json_type)
3049
+ @ds.insert(j)
3050
+ @ds.count.must_equal 1
3051
+ rs = @ds.all
3052
+ v = rs.first[:j]
3053
+ v.class.must_equal(Sequel::Postgres::PGArray)
3054
+ v.to_a.must_be_kind_of(Array)
3055
+ v.map(&:class).must_equal raw.map(&:class)
3056
+ v.must_equal raw
3057
+ v.to_a.must_equal raw
3058
+
3059
+ @db.wrap_json_primitives = true
3060
+ j = Sequel.pg_array(raw.map(&pg_json_wrap), json_type)
3061
+ @ds.insert(j)
3062
+ rs = @ds.all
3063
+ v = rs.first[:j]
3064
+ v.class.must_equal(Sequel::Postgres::PGArray)
3065
+ v.to_a.must_be_kind_of(Array)
3066
+ v.map(&:class).each{|c| c.ancestors.must_include(object_class)}
3067
+ [v, v.to_a].each do |v0|
3068
+ v0.zip(raw) do |v1, r1|
3069
+ if r1.nil?
3070
+ v1.must_be_nil
3071
+ v1.__getobj__.must_be_nil
3072
+ else
3073
+ v1.must_equal r1
3074
+ v1.__getobj__.must_equal r1
3075
+ end
3076
+ end
3077
+ end
3078
+ @ds.delete
3079
+ @ds.insert(rs.first)
3080
+ @ds.all[0][:j].zip(rs[0][:j]) do |v1, r1|
3081
+ if v1.__getobj__.nil?
3082
+ v1.must_be_nil
3083
+ v1.__getobj__.must_be_nil
3084
+ else
3085
+ v1.must_equal r1
3086
+ v1.must_equal r1.__getobj__
3087
+ v1.__getobj__.must_equal r1
3088
+ v1.__getobj__.must_equal r1.__getobj__
3089
+ end
3090
+ end
3091
+ end
3092
+
3002
3093
  it 'with models' do
3003
3094
  @db.create_table!(:items) do
3004
3095
  primary_key :id
3005
3096
  column :h, json_type
3006
3097
  end
3007
3098
  c = Class.new(Sequel::Model(@db[:items]))
3099
+ c.create(:h=>@h).h.must_equal @h
3100
+ c.create(:h=>@a).h.must_equal @a
3008
3101
  c.create(:h=>pg_json.call(@h)).h.must_equal @h
3009
3102
  c.create(:h=>pg_json.call(@a)).h.must_equal @a
3010
3103
  end
3011
3104
 
3105
+ it 'with models with json primitives' do
3106
+ @db.create_table!(:items) do
3107
+ primary_key :id
3108
+ column :h, json_type
3109
+ end
3110
+ c = Class.new(Sequel::Model(@db[:items]))
3111
+
3112
+ ['str', 1, 2.5, nil, true, false].each do |v|
3113
+ @db.wrap_json_primitives = nil
3114
+ cv = c[c.insert(:h=>pg_json_wrap.call(v))]
3115
+ cv.h.class.ancestors.wont_include(object_class)
3116
+ if v.nil?
3117
+ cv.h.must_be_nil
3118
+ else
3119
+ cv.h.must_equal v
3120
+ end
3121
+
3122
+ @db.wrap_json_primitives = true
3123
+ cv.refresh
3124
+ cv.h.class.ancestors.must_include(object_class)
3125
+ cv.save
3126
+ cv.refresh
3127
+ cv.h.class
3128
+
3129
+ if v.nil?
3130
+ cv.h.must_be_nil
3131
+ else
3132
+ cv.h.must_equal v
3133
+ end
3134
+
3135
+ c.new(:h=>cv.h).h.class.ancestors.must_include(object_class)
3136
+ end
3137
+
3138
+ v = c.new(:h=>'{}').h
3139
+ v.class.must_equal hash_class
3140
+ v.must_equal({})
3141
+ @db.typecast_json_strings = true
3142
+ v = c.new(:h=>'{}').h
3143
+ v.class.must_equal str_class
3144
+ v.must_equal '{}'
3145
+
3146
+ c.new(:h=>'str').h.class.ancestors.must_include(object_class)
3147
+ c.new(:h=>'str').h.must_equal 'str'
3148
+ c.new(:h=>1).h.class.ancestors.must_include(object_class)
3149
+ c.new(:h=>1).h.must_equal 1
3150
+ c.new(:h=>2.5).h.class.ancestors.must_include(object_class)
3151
+ c.new(:h=>2.5).h.must_equal 2.5
3152
+ c.new(:h=>true).h.class.ancestors.must_include(object_class)
3153
+ c.new(:h=>true).h.must_equal true
3154
+ c.new(:h=>false).h.class.ancestors.must_include(object_class)
3155
+ c.new(:h=>false).h.must_equal false
3156
+
3157
+ c.new(:h=>nil).h.class.ancestors.wont_include(object_class)
3158
+ c.new(:h=>nil).h.must_be_nil
3159
+ end
3160
+
3012
3161
  it 'with empty json default values and defaults_setter plugin' do
3013
3162
  @db.create_table!(:items) do
3014
3163
  column :h, json_type, :default=>hash_class.new({})
@@ -3043,6 +3192,36 @@ describe 'PostgreSQL json type' do
3043
3192
  @ds.get(:i).must_equal j
3044
3193
  end if uses_pg_or_jdbc
3045
3194
 
3195
+ it 'use json primitives in bound variables' do
3196
+ @db.create_table!(:items){column :i, json_type}
3197
+ @db.wrap_json_primitives = true
3198
+ raw = ['str', 1, 2.5, nil, true, false]
3199
+ raw.each do |v|
3200
+ @ds.delete
3201
+ @ds.call(:insert, {:i=>@db.get(pg_json_wrap.call(v))}, {:i=>:$i})
3202
+ rv = @ds.get(:i)
3203
+ rv.class.ancestors.must_include(object_class)
3204
+ if v.nil?
3205
+ rv.must_be_nil
3206
+ else
3207
+ rv.must_equal v
3208
+ end
3209
+ end
3210
+
3211
+ @db.create_table!(:items){column :i, json_array_type}
3212
+ j = Sequel.pg_array(raw.map(&pg_json_wrap), json_type)
3213
+ @ds.call(:insert, {:i=>j}, {:i=>:$i})
3214
+ @ds.all[0][:i].zip(raw) do |v1, r1|
3215
+ if v1.__getobj__.nil?
3216
+ v1.must_be_nil
3217
+ v1.__getobj__.must_be_nil
3218
+ else
3219
+ v1.must_equal r1
3220
+ v1.__getobj__.must_equal r1
3221
+ end
3222
+ end
3223
+ end if uses_pg_or_jdbc
3224
+
3046
3225
  it 'operations/functions with pg_json_ops' do
3047
3226
  Sequel.extension :pg_json_ops
3048
3227
  jo = pg_json.call('a'=>1, 'b'=>{'c'=>2, 'd'=>{'e'=>3}}).op
@@ -3,6 +3,8 @@ require_relative "spec_helper"
3
3
  Sequel.extension :pg_array, :pg_json
4
4
 
5
5
  describe "pg_json extension" do
6
+ integer_class = RUBY_VERSION >= '2.4' ? Integer : Fixnum
7
+
6
8
  before(:all) do
7
9
  m = Sequel::Postgres
8
10
  @m = m::JSONDatabaseMethods
@@ -29,7 +31,7 @@ describe "pg_json extension" do
29
31
  cp[3807].call("{[]}").must_equal [@bac.new([])]
30
32
  end
31
33
 
32
- it "should parse json strings correctly" do
34
+ deprecated "should parse json strings correctly" do
33
35
  @m.parse_json('[]').class.must_equal(@ac)
34
36
  @m.parse_json('[]').to_a.must_equal []
35
37
  @m.parse_json('[1]').to_a.must_equal [1]
@@ -40,46 +42,82 @@ describe "pg_json extension" do
40
42
  @m.parse_json('{"a": "b"}').to_hash.must_equal('a'=>'b')
41
43
  @m.parse_json('{"a": "b", "c": [1, 2, 3]}').to_hash.must_equal('a'=>'b', 'c'=>[1, 2, 3])
42
44
  @m.parse_json('{"a": "b", "c": {"d": "e"}}').to_hash.must_equal('a'=>'b', 'c'=>{'d'=>'e'})
45
+ proc{@m.parse_json("a")}.must_raise Sequel::InvalidValue
46
+
47
+ begin
48
+ Sequel.instance_eval do
49
+ alias pj parse_json
50
+ def parse_json(v)
51
+ {'1'=>1, "'a'"=>'a', 'true'=>true, 'false'=>false, 'null'=>nil, 'o'=>Object.new, '[one]'=>[1]}.fetch(v){pj(v)}
52
+ end
53
+ end
54
+ proc{@m.parse_json('o')}.must_raise(Sequel::InvalidValue)
55
+ ensure
56
+ Sequel.instance_eval do
57
+ alias parse_json pj
58
+ end
59
+ end
43
60
  end
44
61
 
45
- it "should parse json and non-json plain strings, integers, and floats correctly in db_parse_json" do
62
+ deprecated "should parse json and non-json plain strings, integers, and floats correctly in db_parse_json" do
46
63
  @m.db_parse_json('{"a": "b", "c": {"d": "e"}}').to_hash.must_equal('a'=>'b', 'c'=>{'d'=>'e'})
47
64
  @m.db_parse_json('[1, [2], {"a": "b"}]').to_a.must_equal [1, [2], {'a'=>'b'}]
48
65
  @m.db_parse_json('1').must_equal 1
49
66
  @m.db_parse_json('"b"').must_equal 'b'
50
67
  @m.db_parse_json('1.1').must_equal 1.1
68
+ proc{@m.db_parse_json("a")}.must_raise Sequel::InvalidValue
51
69
  end
52
70
 
53
- it "should parse json and non-json plain strings, integers, and floats correctly in db_parse_jsonb" do
71
+ deprecated "should parse jsonb and non-jsonb plain strings, integers, and floats correctly in db_parse_jsonb" do
54
72
  @m.db_parse_jsonb('{"a": "b", "c": {"d": "e"}}').to_hash.must_equal('a'=>'b', 'c'=>{'d'=>'e'})
55
73
  @m.db_parse_jsonb('[1, [2], {"a": "b"}]').to_a.must_equal [1, [2], {'a'=>'b'}]
56
74
  @m.db_parse_jsonb('1').must_equal 1
57
75
  @m.db_parse_jsonb('"b"').must_equal 'b'
58
76
  @m.db_parse_jsonb('1.1').must_equal 1.1
77
+ proc{@m.db_parse_jsonb("a")}.must_raise Sequel::InvalidValue
59
78
  end
60
79
 
61
- it "should raise an error when attempting to parse invalid json" do
62
- proc{@m.parse_json('')}.must_raise(Sequel::InvalidValue)
63
- proc{@m.parse_json('a')}.must_raise(Sequel::InvalidValue)
80
+ it "should parse json and non-json plain strings, integers, and floats correctly in conversion_proc" do
81
+ cp = @db.conversion_procs[114]
82
+ cp.call('{"a": "b", "c": {"d": "e"}}').to_hash.must_equal('a'=>'b', 'c'=>{'d'=>'e'})
83
+ cp.call('[1, [2], {"a": "b"}]').to_a.must_equal [1, [2], {'a'=>'b'}]
84
+ cp.call('1').must_equal 1
85
+ cp.call('"b"').must_equal 'b'
86
+ cp.call('1.1').must_equal 1.1
87
+ end
64
88
 
65
- begin
66
- Sequel.instance_eval do
67
- alias pj parse_json
68
- def parse_json(v)
69
- {'1'=>1, "'a'"=>'a', 'true'=>true, 'false'=>false, 'null'=>nil, 'o'=>Object.new, '[one]'=>[1]}.fetch(v){pj(v)}
89
+ it "should parse jsonb and non-jsonb plain strings, integers, and floats correctly in conversion_proc" do
90
+ cp = @db.conversion_procs[3802]
91
+ cp.call('{"a": "b", "c": {"d": "e"}}').to_hash.must_equal('a'=>'b', 'c'=>{'d'=>'e'})
92
+ cp.call('[1, [2], {"a": "b"}]').to_a.must_equal [1, [2], {'a'=>'b'}]
93
+ cp.call('1').must_equal 1
94
+ cp.call('"b"').must_equal 'b'
95
+ cp.call('1.1').must_equal 1.1
96
+ end
97
+
98
+ it "should raise an error when attempting to parse invalid json" do
99
+ [114, 3802].each do |oid|
100
+ cp = @db.conversion_procs[oid]
101
+ proc{cp.call('a')}.must_raise(Sequel::InvalidValue)
102
+
103
+ begin
104
+ Sequel.instance_eval do
105
+ alias pj parse_json
106
+ def parse_json(v)
107
+ {'1'=>1, "'a'"=>'a', 'true'=>true, 'false'=>false, 'null'=>nil, 'o'=>Object.new, '[one]'=>[1]}.fetch(v){pj(v)}
108
+ end
109
+ end
110
+ cp.call('1').must_equal 1
111
+ cp.call("'a'").must_equal 'a'
112
+ cp.call('true').must_equal true
113
+ cp.call('false').must_equal false
114
+ cp.call('null').must_be_nil
115
+ proc{cp.call('o')}.must_raise(Sequel::InvalidValue)
116
+ cp.call('one').must_equal 1
117
+ ensure
118
+ Sequel.instance_eval do
119
+ alias parse_json pj
70
120
  end
71
- end
72
- @m.parse_json('1').must_equal 1
73
- @m.parse_json("'a'").must_equal 'a'
74
- @m.parse_json('true').must_equal true
75
- @m.parse_json('false').must_equal false
76
- @m.parse_json('null').must_be_nil
77
- proc{@m.parse_json('o')}.must_raise(Sequel::InvalidValue)
78
- @m.db_parse_json('one').must_equal 1
79
- @m.db_parse_jsonb('one').must_equal 1
80
- ensure
81
- Sequel.instance_eval do
82
- alias parse_json pj
83
121
  end
84
122
  end
85
123
  end
@@ -173,6 +211,117 @@ describe "pg_json extension" do
173
211
  @db.bound_variable_arg(Sequel.pg_array([Sequel.pg_jsonb([{"a"=>1}]), Sequel.pg_jsonb("b"=>[1, 2])]), nil).must_equal '{"[{\\"a\\":1}]","{\\"b\\":[1,2]}"}'
174
212
  end
175
213
 
214
+ it "should support using wrapped JSON and JSONB primitives as bound variables" do
215
+ @db.bound_variable_arg(Sequel.pg_json_wrap(1), nil).must_equal '1'
216
+ @db.bound_variable_arg(Sequel.pg_json_wrap(2.5), nil).must_equal '2.5'
217
+ @db.bound_variable_arg(Sequel.pg_json_wrap('a'), nil).must_equal '"a"'
218
+ @db.bound_variable_arg(Sequel.pg_json_wrap(true), nil).must_equal 'true'
219
+ @db.bound_variable_arg(Sequel.pg_json_wrap(false), nil).must_equal 'false'
220
+ @db.bound_variable_arg(Sequel.pg_json_wrap(nil), nil).must_equal 'null'
221
+ end
222
+
223
+ it "should support using json[] and jsonb[] types in bound variables with ruby primitives" do
224
+ @db.bound_variable_arg(Sequel.pg_array([1, 2.5, 'a', true, false, nil].map{|v| Sequel.pg_json_wrap(v)}), nil).must_equal '{"1","2.5","\"a\"","true","false","null"}'
225
+ end
226
+
227
+ it "Sequel.pg_json_wrap should wrap Ruby primitives in JSON wrappers" do
228
+ Sequel.pg_json_wrap({}).class.must_equal Sequel::Postgres::JSONHash
229
+ Sequel.pg_json_wrap({}).must_equal({})
230
+ Sequel.pg_json_wrap([]).class.must_equal Sequel::Postgres::JSONArray
231
+ Sequel.pg_json_wrap([]).must_equal []
232
+ Sequel.pg_json_wrap('a').class.must_equal Sequel::Postgres::JSONString
233
+ Sequel.pg_json_wrap('a').must_equal 'a'
234
+ Sequel.pg_json_wrap(1).class.must_equal Sequel::Postgres::JSONInteger
235
+ Sequel.pg_json_wrap(1).must_equal 1
236
+ Sequel.pg_json_wrap(2.5).class.must_equal Sequel::Postgres::JSONFloat
237
+ Sequel.pg_json_wrap(2.5).must_equal 2.5
238
+ Sequel.pg_json_wrap(true).class.must_equal Sequel::Postgres::JSONTrue
239
+ Sequel.pg_json_wrap(true).must_equal true
240
+ Sequel.pg_json_wrap(false).class.must_equal Sequel::Postgres::JSONFalse
241
+ Sequel.pg_json_wrap(false).must_equal false
242
+ Sequel.pg_json_wrap(nil).class.must_equal Sequel::Postgres::JSONNull
243
+ Sequel.pg_json_wrap(nil).must_be_nil
244
+ end
245
+
246
+ it "Sequel.pg_json_wrap should fail when passed an unsupported object" do
247
+ proc{Sequel.pg_json_wrap(Object.new)}.must_raise Sequel::Error
248
+ end
249
+
250
+ it "Sequel.pg_jsonb_wrap should wrap Ruby primitives in JSONB wrappers" do
251
+ Sequel.pg_jsonb_wrap({}).class.must_equal Sequel::Postgres::JSONBHash
252
+ Sequel.pg_jsonb_wrap({}).must_equal({})
253
+ Sequel.pg_jsonb_wrap([]).class.must_equal Sequel::Postgres::JSONBArray
254
+ Sequel.pg_jsonb_wrap([]).must_equal []
255
+ Sequel.pg_jsonb_wrap('a').class.must_equal Sequel::Postgres::JSONBString
256
+ Sequel.pg_jsonb_wrap('a').must_equal 'a'
257
+ Sequel.pg_jsonb_wrap(1).class.must_equal Sequel::Postgres::JSONBInteger
258
+ Sequel.pg_jsonb_wrap(1).must_equal 1
259
+ Sequel.pg_jsonb_wrap(2.5).class.must_equal Sequel::Postgres::JSONBFloat
260
+ Sequel.pg_jsonb_wrap(2.5).must_equal 2.5
261
+ Sequel.pg_jsonb_wrap(true).class.must_equal Sequel::Postgres::JSONBTrue
262
+ Sequel.pg_jsonb_wrap(true).must_equal true
263
+ Sequel.pg_jsonb_wrap(false).class.must_equal Sequel::Postgres::JSONBFalse
264
+ Sequel.pg_jsonb_wrap(false).must_equal false
265
+ Sequel.pg_jsonb_wrap(nil).class.must_equal Sequel::Postgres::JSONBNull
266
+ Sequel.pg_jsonb_wrap(nil).must_be_nil
267
+ end
268
+
269
+ it "Sequel.pg_jsonb_wrap should fail when passed an unsupported object" do
270
+ proc{Sequel.pg_jsonb_wrap(Object.new)}.must_raise Sequel::Error
271
+ end
272
+
273
+ it "should not wrap JSON primitives in json and jsonb conversion_proc when not setting wrap_json_primitives" do
274
+ [114, 3802].each do |oid|
275
+ cp = @db.conversion_procs[oid]
276
+ cp.call('1').class.must_equal(integer_class)
277
+ cp.call('1').must_equal 1
278
+ cp.call('2.5').class.must_equal Float
279
+ cp.call('2.5').must_equal 2.5
280
+ cp.call('"a"').class.must_equal String
281
+ cp.call('"a"').must_equal 'a'
282
+ cp.call('true').class.must_equal TrueClass
283
+ cp.call('true').must_equal true
284
+ cp.call('false').class.must_equal FalseClass
285
+ cp.call('false').must_equal false
286
+ cp.call('null').class.must_equal NilClass
287
+ cp.call('null').must_be_nil
288
+ end
289
+ end
290
+
291
+ it "should wrap JSON primitives in json conversion_proc when setting wrap_json_primitives" do
292
+ cp = @db.conversion_procs[114]
293
+ @db.wrap_json_primitives = true
294
+ cp.call('1').class.must_equal Sequel::Postgres::JSONInteger
295
+ cp.call('1').must_equal 1
296
+ cp.call('2.5').class.must_equal Sequel::Postgres::JSONFloat
297
+ cp.call('2.5').must_equal 2.5
298
+ cp.call('"a"').class.must_equal Sequel::Postgres::JSONString
299
+ cp.call('"a"').must_equal "a"
300
+ cp.call('true').class.must_equal Sequel::Postgres::JSONTrue
301
+ cp.call('true').must_equal true
302
+ cp.call('false').class.must_equal Sequel::Postgres::JSONFalse
303
+ cp.call('false').must_equal false
304
+ cp.call('null').class.must_equal Sequel::Postgres::JSONNull
305
+ cp.call('null').must_be_nil
306
+ end
307
+
308
+ it "should wrap JSON primitives in jsonb conversion_proc when setting wrap_json_primitives" do
309
+ cp = @db.conversion_procs[3802]
310
+ @db.wrap_json_primitives = true
311
+ cp.call('1').class.must_equal Sequel::Postgres::JSONBInteger
312
+ cp.call('1').must_equal 1
313
+ cp.call('2.5').class.must_equal Sequel::Postgres::JSONBFloat
314
+ cp.call('2.5').must_equal 2.5
315
+ cp.call('"a"').class.must_equal Sequel::Postgres::JSONBString
316
+ cp.call('"a"').must_equal "a"
317
+ cp.call('true').class.must_equal Sequel::Postgres::JSONBTrue
318
+ cp.call('true').must_equal true
319
+ cp.call('false').class.must_equal Sequel::Postgres::JSONBFalse
320
+ cp.call('false').must_equal false
321
+ cp.call('null').class.must_equal Sequel::Postgres::JSONBNull
322
+ cp.call('null').must_be_nil
323
+ end
324
+
176
325
  it "should parse json type from the schema correctly" do
177
326
  @db.fetch = [{:name=>'id', :db_type=>'integer'}, {:name=>'i', :db_type=>'json'}]
178
327
  @db.schema(:items).map{|e| e[1][:type]}.must_equal [:integer, :json]
@@ -229,8 +378,22 @@ describe "pg_json extension" do
229
378
  @db.typecast_value(:json, '[]').class.must_equal(@ac)
230
379
  @db.typecast_value(:json, '{"a": "b"}').must_equal Sequel.pg_json("a"=>"b")
231
380
  @db.typecast_value(:json, '{"a": "b"}').class.must_equal(@hc)
232
- proc{@db.typecast_value(:json, '')}.must_raise(Sequel::InvalidValue)
233
- proc{@db.typecast_value(:json, 1)}.must_raise(Sequel::InvalidValue)
381
+ @db.typecast_value(:json, 1).class.must_equal Sequel::Postgres::JSONInteger
382
+ @db.typecast_value(:json, 1).must_equal 1
383
+ @db.typecast_value(:json, 2.5).class.must_equal Sequel::Postgres::JSONFloat
384
+ @db.typecast_value(:json, 2.5).must_equal 2.5
385
+ @db.typecast_value(:json, true).class.must_equal Sequel::Postgres::JSONTrue
386
+ @db.typecast_value(:json, true).must_equal true
387
+ @db.typecast_value(:json, false).class.must_equal Sequel::Postgres::JSONFalse
388
+ @db.typecast_value(:json, false).must_equal false
389
+ @db.typecast_value(:json, nil).class.must_equal NilClass
390
+ @db.typecast_value(:json, nil).must_be_nil
391
+ proc{@db.typecast_value(:json, 'a')}.must_raise(Sequel::InvalidValue)
392
+ proc{@db.typecast_value(:json, Object.new)}.must_raise(Sequel::InvalidValue)
393
+
394
+ @db.typecast_json_strings = true
395
+ @db.typecast_value(:json, '[]').class.must_equal(Sequel::Postgres::JSONString)
396
+ @db.typecast_value(:json, '[]').must_equal '[]'
234
397
  end
235
398
 
236
399
  it "should support typecasting for the jsonb type" do
@@ -250,13 +413,27 @@ describe "pg_json extension" do
250
413
  @db.typecast_value(:jsonb, '[]').class.must_equal(@bac)
251
414
  @db.typecast_value(:jsonb, '{"a": "b"}').must_equal Sequel.pg_jsonb("a"=>"b")
252
415
  @db.typecast_value(:jsonb, '{"a": "b"}').class.must_equal(@bhc)
253
- proc{@db.typecast_value(:jsonb, '')}.must_raise(Sequel::InvalidValue)
254
- proc{@db.typecast_value(:jsonb, 1)}.must_raise(Sequel::InvalidValue)
416
+ @db.typecast_value(:jsonb, 1).class.must_equal Sequel::Postgres::JSONBInteger
417
+ @db.typecast_value(:jsonb, 1).must_equal 1
418
+ @db.typecast_value(:jsonb, 2.5).class.must_equal Sequel::Postgres::JSONBFloat
419
+ @db.typecast_value(:jsonb, 2.5).must_equal 2.5
420
+ @db.typecast_value(:jsonb, true).class.must_equal Sequel::Postgres::JSONBTrue
421
+ @db.typecast_value(:jsonb, true).must_equal true
422
+ @db.typecast_value(:jsonb, false).class.must_equal Sequel::Postgres::JSONBFalse
423
+ @db.typecast_value(:jsonb, false).must_equal false
424
+ @db.typecast_value(:jsonb, nil).class.must_equal NilClass
425
+ @db.typecast_value(:jsonb, nil).must_be_nil
426
+ proc{@db.typecast_value(:jsonb, 'a')}.must_raise(Sequel::InvalidValue)
427
+ proc{@db.typecast_value(:jsonb, Object.new)}.must_raise(Sequel::InvalidValue)
428
+
429
+ @db.typecast_json_strings = true
430
+ @db.typecast_value(:jsonb, '[]').class.must_equal(Sequel::Postgres::JSONBString)
431
+ @db.typecast_value(:jsonb, '[]').must_equal '[]'
255
432
  end
256
433
 
257
434
  it "should return correct results for Database#schema_type_class" do
258
- @db.schema_type_class(:json).must_equal [Sequel::Postgres::JSONHash, Sequel::Postgres::JSONArray]
259
- @db.schema_type_class(:jsonb).must_equal [Sequel::Postgres::JSONBHash, Sequel::Postgres::JSONBArray]
435
+ @db.schema_type_class(:json).must_equal [Sequel::Postgres::JSONObject]
436
+ @db.schema_type_class(:jsonb).must_equal [Sequel::Postgres::JSONBObject]
260
437
  @db.schema_type_class(:integer).must_equal Integer
261
438
  end
262
439
  end