sequel 5.20.0 → 5.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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