sequel 4.28.0 → 4.29.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +20 -0
- data/README.rdoc +4 -4
- data/doc/opening_databases.rdoc +2 -6
- data/doc/release_notes/4.29.0.txt +41 -0
- data/lib/sequel/adapters/oracle.rb +1 -1
- data/lib/sequel/adapters/shared/postgres.rb +1 -1
- data/lib/sequel/adapters/sqlanywhere.rb +3 -3
- data/lib/sequel/database/query.rb +6 -1
- data/lib/sequel/database/transactions.rb +3 -3
- data/lib/sequel/dataset/sql.rb +8 -3
- data/lib/sequel/extensions/date_arithmetic.rb +3 -0
- data/lib/sequel/plugins/json_serializer.rb +25 -4
- data/lib/sequel/plugins/uuid.rb +72 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/postgres_spec.rb +1 -1
- data/spec/core/database_spec.rb +35 -0
- data/spec/extensions/date_arithmetic_spec.rb +17 -0
- data/spec/extensions/json_serializer_spec.rb +7 -0
- data/spec/extensions/uuid_spec.rb +106 -0
- data/spec/integration/prepared_statement_test.rb +3 -3
- data/spec/integration/schema_test.rb +1 -1
- data/spec/integration/transaction_test.rb +22 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f1baf17a3ed5aedeadf0002e4e68ac8e2e27bdc2
|
4
|
+
data.tar.gz: 9ceec8f5898df4025b6cf5239f461dee5595ebeb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a2c9116e35e8ff8a536530cff484f2d82fac1916db18d8d4b4666359c6ce1f6a67aeb855feb173128f874a179bc75ef10a22bd326ecf48ad6c3cfbe6f3f3b8d3
|
7
|
+
data.tar.gz: 07d8ee3fb38aeae9caa9344756826a7e43fa19bd5786948525b427e9d64c3714ee06d452299b310bb7d30666e16ee0af64f663de7bb9a3dbd3b2fd0f2c5255dd
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
=== 4.29.0 (2015-12-01)
|
2
|
+
|
3
|
+
* Add Model#json_serializer_opts method to json_serializer plugin, allowing for setting to_json defaults on per-instance basis (jeremyevans)
|
4
|
+
|
5
|
+
* Add uuid plugin for automatically setting UUID column when creating a model object (pdrakeweb, jeremyevans) (#1106)
|
6
|
+
|
7
|
+
* Allow the sqlanywhere adapter to work with sharding (jeremyevans)
|
8
|
+
|
9
|
+
* Support blobs as bound variables in the oracle adapter (jeremyevans) (#1104)
|
10
|
+
|
11
|
+
* Order by best results first when using the Database#full_text_search :rank option on PostgreSQL (chanks) (#1101)
|
12
|
+
|
13
|
+
* Run Database#table_exists? inside a savepoint if currently in a transaction and the database supports savepoints (jeremyevans) (#1100)
|
14
|
+
|
15
|
+
* Allow Database#transaction :retry_on option to work when using savepoints (jeremyevans)
|
16
|
+
|
17
|
+
* Allow for external adapters to implement Dataset#date_add_sql_append to integrate with the date_arithmetic extension (jeremyevans)
|
18
|
+
|
19
|
+
* Add Dataset#insert_empty_columns_values private method for easy overriding for databases that don't support INSERT with DEFAULT VALUES (jeremyevans)
|
20
|
+
|
1
21
|
=== 4.28.0 (2015-11-02)
|
2
22
|
|
3
23
|
* Add boolean_subsets plugin, which adds a subset for each boolean column (jeremyevans)
|
data/README.rdoc
CHANGED
@@ -44,7 +44,7 @@ If you have any comments or suggestions please post to the Google group.
|
|
44
44
|
|
45
45
|
require 'sequel'
|
46
46
|
|
47
|
-
DB = Sequel.sqlite # memory database
|
47
|
+
DB = Sequel.sqlite # memory database, requires sqlite3
|
48
48
|
|
49
49
|
DB.create_table :items do
|
50
50
|
primary_key :id
|
@@ -109,11 +109,11 @@ Or getting results as a hash via +to_hash+, with one column as key and another a
|
|
109
109
|
To connect to a database you simply provide <tt>Sequel.connect</tt> with a URL:
|
110
110
|
|
111
111
|
require 'sequel'
|
112
|
-
DB = Sequel.connect('sqlite://blog.db')
|
112
|
+
DB = Sequel.connect('sqlite://blog.db') # requires sqlite3
|
113
113
|
|
114
114
|
The connection URL can also include such stuff as the user name, password, and port:
|
115
115
|
|
116
|
-
DB = Sequel.connect('postgres://user:password@host:port/database_name')
|
116
|
+
DB = Sequel.connect('postgres://user:password@host:port/database_name') # requires pg
|
117
117
|
|
118
118
|
You can also specify optional parameters, such as the connection pool size, or loggers for logging SQL queries:
|
119
119
|
|
@@ -267,7 +267,7 @@ issues that you should be aware of when using Sequel.
|
|
267
267
|
|
268
268
|
Counting records is easy using +count+:
|
269
269
|
|
270
|
-
posts.where(
|
270
|
+
posts.where(Sequel.like(:category, '%ruby%')).count
|
271
271
|
# SELECT COUNT(*) FROM posts WHERE category LIKE '%ruby%'
|
272
272
|
|
273
273
|
And you can also query maximum/minimum values via +max+ and +min+:
|
data/doc/opening_databases.rdoc
CHANGED
@@ -269,12 +269,8 @@ The following additional options are supported:
|
|
269
269
|
=== mysql2
|
270
270
|
|
271
271
|
This is a newer MySQL adapter that does typecasting in C, so it is often faster than the
|
272
|
-
mysql adapter.
|
273
|
-
|
274
|
-
|
275
|
-
The following additional options are supported:
|
276
|
-
|
277
|
-
:flags :: Override the flags to use for the connection (e.g. ::Mysql2::Client::MULTI_STATEMENTS)
|
272
|
+
mysql adapter. The options given are passed to Mysql2::Client.new, see the mysql2 documentation
|
273
|
+
for details on what options are supported.
|
278
274
|
|
279
275
|
=== odbc
|
280
276
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A uuid plugin has now been added. This plugin will automatically
|
4
|
+
create a uuid for newly created model objects.
|
5
|
+
|
6
|
+
Model.plugin :uuid
|
7
|
+
Model.create.uuid => # some UUID
|
8
|
+
|
9
|
+
* Model#json_serializer_opts has been added to the json_serializer
|
10
|
+
plugin, allowing you to override the JSON serialization options
|
11
|
+
on a per instance basis without passing the options directly
|
12
|
+
to Model#to_json. This is useful if you are including the model
|
13
|
+
instance inside another datastructure that will be serialized
|
14
|
+
to JSON.
|
15
|
+
|
16
|
+
obj.json_serializer_opts(:root => true)
|
17
|
+
[obj].to_json
|
18
|
+
# => '[{"obj":{"id":1,"name":"Foo"}}]'
|
19
|
+
|
20
|
+
= Other Improvements
|
21
|
+
|
22
|
+
* The Database#transaction :retry_on option now works when using
|
23
|
+
savepoints.
|
24
|
+
|
25
|
+
* Calling Database#table_exists? inside a transaction will now use
|
26
|
+
a savepoint if the database supports it, so that if the table
|
27
|
+
doesn't exist, it will not affect the state of the transaction.
|
28
|
+
|
29
|
+
* Blobs can now be used as bound variables in the oracle adapter.
|
30
|
+
|
31
|
+
* The sqlanywhere adapter now works with database sharding.
|
32
|
+
|
33
|
+
* The Dataset#full_text_search :rank option has been fixed to order
|
34
|
+
by rank descending instead of ascending.
|
35
|
+
|
36
|
+
* External adapters that do not support INSERT with DEFAULT VALUES
|
37
|
+
can now override Dataset#insert_empty_columns_values to set
|
38
|
+
the columns and values to use for an empty INSERT.
|
39
|
+
|
40
|
+
* External adapters can now implement Dataset#date_add_sql_append
|
41
|
+
to integrate with the date_arithmetic extension.
|
@@ -122,7 +122,7 @@ module Sequel
|
|
122
122
|
when BigDecimal
|
123
123
|
arg = arg.to_f
|
124
124
|
when ::Sequel::SQL::Blob
|
125
|
-
|
125
|
+
arg = ::OCI8::BLOB.new(conn, arg)
|
126
126
|
end
|
127
127
|
if t = PS_TYPES[type]
|
128
128
|
cursor.bind_param(i, arg, t)
|
@@ -79,19 +79,19 @@ module Sequel
|
|
79
79
|
|
80
80
|
# Returns number of rows affected
|
81
81
|
def execute_dui(sql, opts=OPTS)
|
82
|
-
synchronize do |conn|
|
82
|
+
synchronize(opts[:server]) do |conn|
|
83
83
|
_execute(conn, :rows, sql, opts)
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
87
87
|
def execute(sql, opts=OPTS, &block)
|
88
|
-
synchronize do |conn|
|
88
|
+
synchronize(opts[:server]) do |conn|
|
89
89
|
_execute(conn, :select, sql, opts, &block)
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
93
|
def execute_insert(sql, opts=OPTS)
|
94
|
-
synchronize do |conn|
|
94
|
+
synchronize(opts[:server]) do |conn|
|
95
95
|
_execute(conn, :insert, sql, opts)
|
96
96
|
end
|
97
97
|
end
|
@@ -191,7 +191,12 @@ module Sequel
|
|
191
191
|
def table_exists?(name)
|
192
192
|
sch, table_name = schema_and_table(name)
|
193
193
|
name = SQL::QualifiedIdentifier.new(sch, table_name) if sch
|
194
|
-
|
194
|
+
ds = from(name)
|
195
|
+
if in_transaction? && supports_savepoints?
|
196
|
+
transaction(:savepoint=>true){_table_exists?(ds)}
|
197
|
+
else
|
198
|
+
_table_exists?(ds)
|
199
|
+
end
|
195
200
|
true
|
196
201
|
rescue DatabaseError
|
197
202
|
false
|
@@ -96,12 +96,12 @@ module Sequel
|
|
96
96
|
else
|
97
97
|
synchronize(opts[:server]) do |conn|
|
98
98
|
if already_in_transaction?(conn, opts)
|
99
|
-
if opts[:retrying]
|
100
|
-
raise Sequel::Error, "cannot set :retry_on options if you are already inside a transaction"
|
101
|
-
end
|
102
99
|
if opts[:savepoint] != false && (stack = _trans(conn)[:savepoints]) && stack.last
|
103
100
|
_transaction(conn, Hash[opts].merge!(:savepoint=>true), &block)
|
104
101
|
else
|
102
|
+
if opts[:retrying]
|
103
|
+
raise Sequel::Error, "cannot set :retry_on options if you are already inside a transaction"
|
104
|
+
end
|
105
105
|
return yield(conn)
|
106
106
|
end
|
107
107
|
else
|
data/lib/sequel/dataset/sql.rb
CHANGED
@@ -46,12 +46,11 @@ module Sequel
|
|
46
46
|
end
|
47
47
|
|
48
48
|
if values.is_a?(Array) && values.empty? && !insert_supports_empty_values?
|
49
|
-
columns =
|
50
|
-
values = [DEFAULT]
|
49
|
+
columns, values = insert_empty_columns_values
|
51
50
|
end
|
52
51
|
clone(:columns=>columns, :values=>values).send(:_insert_sql)
|
53
52
|
end
|
54
|
-
|
53
|
+
|
55
54
|
# Append a literal representation of a value to the given SQL string.
|
56
55
|
#
|
57
56
|
# If an unsupported object is given, an +Error+ is raised.
|
@@ -1116,6 +1115,12 @@ module Sequel
|
|
1116
1115
|
end
|
1117
1116
|
end
|
1118
1117
|
|
1118
|
+
# The columns and values to use for an empty insert if the database doesn't support
|
1119
|
+
# INSERT with DEFAULT VALUES.
|
1120
|
+
def insert_empty_columns_values
|
1121
|
+
[[columns.last], [DEFAULT]]
|
1122
|
+
end
|
1123
|
+
|
1119
1124
|
def insert_insert_sql(sql)
|
1120
1125
|
sql << INSERT
|
1121
1126
|
end
|
@@ -36,6 +36,12 @@ module Sequel
|
|
36
36
|
# album.to_json(:root => true)
|
37
37
|
# # => '{"album":{"id":1,"name":"RF","artist_id":2}}'
|
38
38
|
#
|
39
|
+
# You can specify JSON serialization options to use later:
|
40
|
+
#
|
41
|
+
# album.json_serializer_opts(:root => true)
|
42
|
+
# [album].to_json
|
43
|
+
# # => '[{"album":{"id":1,"name":"RF","artist_id":2}}]'
|
44
|
+
#
|
39
45
|
# Additionally, +to_json+ also exists as a class and dataset method, both
|
40
46
|
# of which return all objects in the dataset:
|
41
47
|
#
|
@@ -239,6 +245,20 @@ module Sequel
|
|
239
245
|
self
|
240
246
|
end
|
241
247
|
|
248
|
+
# Set the json serialization options that will be used by default
|
249
|
+
# in future calls to +to_json+. This is designed for cases where
|
250
|
+
# the model object will be used inside another data structure
|
251
|
+
# which to_json is called on, and as such will not allow passing
|
252
|
+
# of arguments to +to_json+.
|
253
|
+
#
|
254
|
+
# Example:
|
255
|
+
#
|
256
|
+
# obj.json_serializer_opts(:only=>:name)
|
257
|
+
# [obj].to_json # => '[{"name":"..."}]'
|
258
|
+
def json_serializer_opts(opts=OPTS)
|
259
|
+
@json_serializer_opts = Hash[@json_serializer_opts||OPTS].merge!(opts)
|
260
|
+
end
|
261
|
+
|
242
262
|
# Return a string in JSON format. Accepts the following
|
243
263
|
# options:
|
244
264
|
#
|
@@ -257,12 +277,13 @@ module Sequel
|
|
257
277
|
# string is given, use the string as the key, otherwise
|
258
278
|
# use an underscored version of the model's name.
|
259
279
|
def to_json(*a)
|
260
|
-
|
261
|
-
|
280
|
+
opts = model.json_serializer_opts
|
281
|
+
opts = Hash[opts].merge!(@json_serializer_opts) if @json_serializer_opts
|
282
|
+
if (arg_opts = a.first).is_a?(Hash)
|
283
|
+
opts = Hash[opts].merge!(arg_opts)
|
262
284
|
a = []
|
263
|
-
else
|
264
|
-
opts = model.json_serializer_opts
|
265
285
|
end
|
286
|
+
|
266
287
|
vals = values
|
267
288
|
cols = if only = opts[:only]
|
268
289
|
Array(only)
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
module Sequel
|
4
|
+
module Plugins
|
5
|
+
# The uuid plugin creates hooks that automatically create a uuid for every
|
6
|
+
# instance. Note that this uses SecureRandom.uuid to create UUIDs, and
|
7
|
+
# that method is not defined on ruby 1.8.7. If you would like to use this
|
8
|
+
# on ruby 1.8.7, you need to override the Model#create_uuid private method
|
9
|
+
# to return a valid uuid.
|
10
|
+
#
|
11
|
+
# Usage:
|
12
|
+
#
|
13
|
+
# # Uuid all model instances using +uuid+
|
14
|
+
# # (called before loading subclasses)
|
15
|
+
# Sequel::Model.plugin :uuid
|
16
|
+
#
|
17
|
+
# # Uuid Album instances, with custom column name
|
18
|
+
# Album.plugin :uuid, :field=>my_uuid
|
19
|
+
module Uuid
|
20
|
+
# Configure the plugin by setting the available options. Note that
|
21
|
+
# if this method is run more than once, previous settings are ignored,
|
22
|
+
# and it will just use the settings given or the default settings. Options:
|
23
|
+
# :field :: The field to hold the uuid (default: :uuid)
|
24
|
+
# :force :: Whether to overwrite an existing uuid (default: false)
|
25
|
+
def self.configure(model, opts=OPTS)
|
26
|
+
model.instance_eval do
|
27
|
+
@uuid_field = opts[:field]||:uuid
|
28
|
+
@uuid_overwrite = opts[:force]||false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module ClassMethods
|
33
|
+
# The field to store the uuid
|
34
|
+
attr_reader :uuid_field
|
35
|
+
|
36
|
+
# Whether to overwrite the create uuid if it already exists
|
37
|
+
def uuid_overwrite?
|
38
|
+
@uuid_overwrite
|
39
|
+
end
|
40
|
+
|
41
|
+
Plugins.inherited_instance_variables(self, :@uuid_field=>nil, :@uuid_overwrite=>nil)
|
42
|
+
end
|
43
|
+
|
44
|
+
module InstanceMethods
|
45
|
+
private
|
46
|
+
|
47
|
+
# Set the uuid when creating
|
48
|
+
def _before_validation
|
49
|
+
set_uuid if new?
|
50
|
+
super
|
51
|
+
end
|
52
|
+
|
53
|
+
# Create a new UUID. This method can be overridden to use a separate
|
54
|
+
# method for creating UUIDs. Note that this method does not work on
|
55
|
+
# ruby 1.8.7, you will have to override it if you are using ruby 1.8.7.
|
56
|
+
def create_uuid
|
57
|
+
SecureRandom.uuid
|
58
|
+
end
|
59
|
+
|
60
|
+
# If the object has accessor methods for the uuid field, and the uuid
|
61
|
+
# value is nil or overwriting it is allowed, set the uuid.
|
62
|
+
def set_uuid(uuid=create_uuid)
|
63
|
+
field = model.uuid_field
|
64
|
+
meth = :"#{field}="
|
65
|
+
if respond_to?(field) && respond_to?(meth) && (model.uuid_overwrite? || get_column_value(field).nil?)
|
66
|
+
set_column_value(meth, uuid)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/sequel/version.rb
CHANGED
@@ -3,7 +3,7 @@ module Sequel
|
|
3
3
|
MAJOR = 4
|
4
4
|
# The minor version of Sequel. Bumped for every non-patch level
|
5
5
|
# release, generally around once a month.
|
6
|
-
MINOR =
|
6
|
+
MINOR = 29
|
7
7
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
8
8
|
# releases that fix regressions from previous versions.
|
9
9
|
TINY = 0
|
@@ -987,7 +987,7 @@ describe "A PostgreSQL database" do
|
|
987
987
|
t2 = "ruby sequel " * 1000
|
988
988
|
@db[:posts].insert(:title=>t1)
|
989
989
|
@db[:posts].insert(:title=>t2)
|
990
|
-
@db[:posts].full_text_search(:title, 'ruby & sequel', :rank=>true).select_map(:title).must_equal [
|
990
|
+
@db[:posts].full_text_search(:title, 'ruby & sequel', :rank=>true).select_map(:title).must_equal [t2, t1]
|
991
991
|
end
|
992
992
|
|
993
993
|
it "should support spatial indexes" do
|
data/spec/core/database_spec.rb
CHANGED
@@ -614,6 +614,17 @@ describe "Database#table_exists?" do
|
|
614
614
|
db.table_exists?(:b).must_equal true
|
615
615
|
db.table_exists?(:c).must_equal true
|
616
616
|
end
|
617
|
+
|
618
|
+
it "should use a savepoint if inside a transaction" do
|
619
|
+
db = Sequel.mock(:fetch=>[Sequel::Error, [], [{:a=>1}]])
|
620
|
+
def db.supports_savepoints?; true end
|
621
|
+
db.transaction do
|
622
|
+
db.table_exists?(:a).must_equal false
|
623
|
+
end
|
624
|
+
db.sqls.must_equal ["BEGIN", "SAVEPOINT autopoint_1", "SELECT NULL AS nil FROM a LIMIT 1", "ROLLBACK TO SAVEPOINT autopoint_1", "COMMIT"]
|
625
|
+
db.table_exists?(:b).must_equal true
|
626
|
+
db.table_exists?(:c).must_equal true
|
627
|
+
end
|
617
628
|
end
|
618
629
|
|
619
630
|
DatabaseTransactionSpecs = shared_description do
|
@@ -964,6 +975,30 @@ describe "Database#transaction with savepoint support" do
|
|
964
975
|
|
965
976
|
include DatabaseTransactionSpecs
|
966
977
|
|
978
|
+
it "should support :retry_on option for automatically retrying transactions when using :savepoint option" do
|
979
|
+
a = []
|
980
|
+
@db.transaction do
|
981
|
+
@db.transaction(:retry_on=>Sequel::SerializationFailure, :savepoint=>true) do
|
982
|
+
a << 1
|
983
|
+
raise Sequel::SerializationFailure if a.length == 1
|
984
|
+
end
|
985
|
+
end
|
986
|
+
@db.sqls.must_equal ["BEGIN", "SAVEPOINT autopoint_1", "ROLLBACK TO SAVEPOINT autopoint_1", "SAVEPOINT autopoint_1", "RELEASE SAVEPOINT autopoint_1", "COMMIT"]
|
987
|
+
a.must_equal [1, 1]
|
988
|
+
end
|
989
|
+
|
990
|
+
it "should support :retry_on option for automatically retrying transactions inside an :auto_savepoint transaction" do
|
991
|
+
a = []
|
992
|
+
@db.transaction(:auto_savepoint=>true) do
|
993
|
+
@db.transaction(:retry_on=>Sequel::SerializationFailure) do
|
994
|
+
a << 1
|
995
|
+
raise Sequel::SerializationFailure if a.length == 1
|
996
|
+
end
|
997
|
+
end
|
998
|
+
@db.sqls.must_equal ["BEGIN", "SAVEPOINT autopoint_1", "ROLLBACK TO SAVEPOINT autopoint_1", "SAVEPOINT autopoint_1", "RELEASE SAVEPOINT autopoint_1", "COMMIT"]
|
999
|
+
a.must_equal [1, 1]
|
1000
|
+
end
|
1001
|
+
|
967
1002
|
it "should support after_commit inside savepoints" do
|
968
1003
|
@db.transaction do
|
969
1004
|
@db.after_commit{@db.execute('foo')}
|
@@ -65,6 +65,23 @@ describe "date_arithmetic extension" do
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
+
it "should use existing method" do
|
69
|
+
db = Sequel.mock
|
70
|
+
db.extend_datasets do
|
71
|
+
def date_add_sql_append(sql, da)
|
72
|
+
interval = ''
|
73
|
+
each_valid_interval_unit(da.interval, Sequel::SQL::DateAdd::DatasetMethods::DEF_DURATION_UNITS) do |value, sql_unit|
|
74
|
+
interval << "#{value} #{sql_unit} "
|
75
|
+
end
|
76
|
+
literal_append(sql, Sequel.function(:da, da.expr, interval))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
db.extension :date_arithmetic
|
80
|
+
db.literal(Sequel.date_add(:a, @h0)).must_equal "da(a, '')"
|
81
|
+
db.literal(Sequel.date_add(:a, @h1)).must_equal "da(a, '1 days ')"
|
82
|
+
db.literal(Sequel.date_add(:a, @h2)).must_equal "da(a, '1 years 1 months 1 days 1 hours 1 minutes 1 seconds ')"
|
83
|
+
end
|
84
|
+
|
68
85
|
it "should correctly literalize on Postgres" do
|
69
86
|
db = dbf.call(:postgres)
|
70
87
|
db.literal(Sequel.date_add(:a, @h0)).must_equal "CAST(a AS timestamp)"
|
@@ -43,6 +43,13 @@ describe "Sequel::Plugins::JsonSerializer" do
|
|
43
43
|
Artist.from_json(Artist.load(:name=>Date.today).to_json).must_equal Artist.load(:name=>Date.today)
|
44
44
|
end
|
45
45
|
|
46
|
+
it "should support setting json_serializer_opts on models" do
|
47
|
+
@artist.json_serializer_opts(:only=>:name)
|
48
|
+
Sequel.parse_json([@artist].to_json).must_equal [{'name'=>@artist.name}]
|
49
|
+
@artist.json_serializer_opts(:include=>{:albums=>{:only=>:name}})
|
50
|
+
Sequel.parse_json([@artist].to_json).must_equal [{'name'=>@artist.name, 'albums'=>[{'name'=>@album.name}]}]
|
51
|
+
end
|
52
|
+
|
46
53
|
it "should handle the :only option" do
|
47
54
|
Artist.from_json(@artist.to_json(:only=>:name)).must_equal Artist.load(:name=>@artist.name)
|
48
55
|
Album.from_json(@album.to_json(:only=>[:id, :name])).must_equal Album.load(:id=>@album.id, :name=>@album.name)
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
|
+
|
3
|
+
describe "Sequel::Plugins::Uuid" do
|
4
|
+
before do
|
5
|
+
uuid = @uuid = '57308544-4e83-47b8-b87f-6f68b987f4f9'
|
6
|
+
@alt_uuid = 'd5d1ec46-5e8e-4a7b-adc9-50e76b819e19'
|
7
|
+
dc = Object.new
|
8
|
+
@c = Class.new(Sequel::Model(:t))
|
9
|
+
@c.class_eval do
|
10
|
+
columns :id, :uuid
|
11
|
+
plugin :uuid
|
12
|
+
def _save_refresh(*) end
|
13
|
+
define_method(:create_uuid) do
|
14
|
+
uuid
|
15
|
+
end
|
16
|
+
db.reset
|
17
|
+
end
|
18
|
+
@c.dataset.autoid = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should handle validations on the uuid field for new objects" do
|
22
|
+
@c.plugin :uuid, :force=>true
|
23
|
+
o = @c.new
|
24
|
+
def o.validate
|
25
|
+
errors.add(model.uuid_field, 'not present') unless send(model.uuid_field)
|
26
|
+
end
|
27
|
+
o.valid?.must_equal true
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should set uuid field when skipping validations" do
|
31
|
+
@c.plugin :uuid
|
32
|
+
@c.new.save(:validate=>false)
|
33
|
+
@c.db.sqls.must_equal ["INSERT INTO t (uuid) VALUES ('#{@uuid}')"]
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should set the uuid field on creation" do
|
37
|
+
o = @c.create
|
38
|
+
@c.db.sqls.must_equal ["INSERT INTO t (uuid) VALUES ('#{@uuid}')"]
|
39
|
+
o.uuid.must_equal @uuid
|
40
|
+
end
|
41
|
+
|
42
|
+
if RUBY_VERSION >= '1.9'
|
43
|
+
it "should allow specifying the uuid field via the :field option" do
|
44
|
+
c = Class.new(Sequel::Model(:t))
|
45
|
+
c.class_eval do
|
46
|
+
columns :id, :u
|
47
|
+
plugin :uuid, :field=>:u
|
48
|
+
def _save_refresh(*) end
|
49
|
+
end
|
50
|
+
o = c.create
|
51
|
+
c.db.sqls.first.must_match(/INSERT INTO t \(u\) VALUES \('[-0-9a-f]+'\)/)
|
52
|
+
o.u.must_match /[-0-9a-f]+/
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should not raise an error if the model doesn't have the uuid column" do
|
57
|
+
@c.columns :id, :x
|
58
|
+
@c.send(:undef_method, :uuid)
|
59
|
+
@c.create(:x=>2)
|
60
|
+
@c.load(:id=>1, :x=>2).save
|
61
|
+
@c.db.sqls.must_equal ["INSERT INTO t (x) VALUES (2)", "UPDATE t SET x = 2 WHERE (id = 1)"]
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should not overwrite an existing uuid value" do
|
65
|
+
o = @c.create(:uuid=>@alt_uuid)
|
66
|
+
@c.db.sqls.must_equal ["INSERT INTO t (uuid) VALUES ('#{@alt_uuid}')"]
|
67
|
+
o.uuid.must_equal @alt_uuid
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should overwrite an existing uuid if the :force option is used" do
|
71
|
+
@c.plugin :uuid, :force=>true
|
72
|
+
o = @c.create(:uuid=>@alt_uuid)
|
73
|
+
@c.db.sqls.must_equal ["INSERT INTO t (uuid) VALUES ('#{@uuid}')"]
|
74
|
+
o.uuid.must_equal @uuid
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should have uuid_field give the uuid field" do
|
78
|
+
@c.uuid_field.must_equal :uuid
|
79
|
+
@c.plugin :uuid, :field=>:u
|
80
|
+
@c.uuid_field.must_equal :u
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should have uuid_overwrite? give the whether to overwrite an existing uuid" do
|
84
|
+
@c.uuid_overwrite?.must_equal false
|
85
|
+
@c.plugin :uuid, :force=>true
|
86
|
+
@c.uuid_overwrite?.must_equal true
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should work with subclasses" do
|
90
|
+
c = Class.new(@c)
|
91
|
+
o = c.create
|
92
|
+
o.uuid.must_equal @uuid
|
93
|
+
c.db.sqls.must_equal ["INSERT INTO t (uuid) VALUES ('#{@uuid}')"]
|
94
|
+
c.create(:uuid=>@alt_uuid).uuid.must_equal @alt_uuid
|
95
|
+
|
96
|
+
c.class_eval do
|
97
|
+
columns :id, :u
|
98
|
+
plugin :uuid, :field=>:u, :force=>true
|
99
|
+
end
|
100
|
+
c2 = Class.new(c)
|
101
|
+
c2.db.reset
|
102
|
+
o = c2.create
|
103
|
+
o.u.must_equal @uuid
|
104
|
+
c2.db.sqls.first.must_match(/INSERT INTO t \([u]\) VALUES \('#{@uuid}'\)/)
|
105
|
+
end
|
106
|
+
end
|
@@ -355,13 +355,13 @@ describe "Bound Argument Types" do
|
|
355
355
|
@ds.literal(@ds.filter(:t=>:$x).prepare(:first, :ps_time).call(:x=>fract_time)[:t]).must_equal @ds.literal(fract_time)
|
356
356
|
end
|
357
357
|
|
358
|
-
cspecify "should handle blob type", [:odbc]
|
358
|
+
cspecify "should handle blob type", [:odbc] do
|
359
359
|
@ds.delete
|
360
360
|
@ds.prepare(:insert, :ps_blob, {:file=>:$x}).call(:x=>@vs[:file])
|
361
361
|
@ds.get(:file).must_equal @vs[:file]
|
362
362
|
end
|
363
363
|
|
364
|
-
cspecify "should handle blob type with special characters", [:odbc]
|
364
|
+
cspecify "should handle blob type with special characters", [:odbc] do
|
365
365
|
@ds.delete
|
366
366
|
blob = Sequel.blob("\"'[]`a0 ")
|
367
367
|
@ds.prepare(:insert, :ps_blob, {:file=>:$x}).call(:x=>blob)
|
@@ -374,7 +374,7 @@ describe "Bound Argument Types" do
|
|
374
374
|
@ds.get(:file).must_equal nil
|
375
375
|
end
|
376
376
|
|
377
|
-
cspecify "should handle blob type with embedded zeros", [:odbc]
|
377
|
+
cspecify "should handle blob type with embedded zeros", [:odbc] do
|
378
378
|
zero_blob = Sequel::SQL::Blob.new("a\0"*100)
|
379
379
|
@ds.delete
|
380
380
|
@ds.prepare(:insert, :ps_blob, {:file=>:$x}).call(:x=>zero_blob)
|
@@ -582,7 +582,7 @@ describe "Database schema modifiers" do
|
|
582
582
|
@db.schema(:items, :reload=>true).map{|x| x.first}.must_equal [:id]
|
583
583
|
@ds.columns!.must_equal [:id]
|
584
584
|
@ds.insert(:id=>'20')
|
585
|
-
@ds.all.must_equal [{:id=>"10"}, {:id=>"20"}]
|
585
|
+
@ds.order(:id).all.must_equal [{:id=>"10"}, {:id=>"20"}]
|
586
586
|
end
|
587
587
|
|
588
588
|
cspecify "should set column types without modifying NULL/NOT NULL", [:jdbc, :db2], [:db2], :oracle, :derby do
|
@@ -84,6 +84,28 @@ describe "Database transactions" do
|
|
84
84
|
end
|
85
85
|
|
86
86
|
if DB.supports_savepoints?
|
87
|
+
it "should handle table_exists? failures inside transactions" do
|
88
|
+
@db.transaction do
|
89
|
+
@d << {:name => '1'}
|
90
|
+
@db.table_exists?(:asadf098asd9asd98sa).must_equal false
|
91
|
+
@d << {:name => '2'}
|
92
|
+
end
|
93
|
+
@d.select_order_map(:name).must_equal %w'1 2'
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should handle table_exists? failures inside savepoints" do
|
97
|
+
@db.transaction do
|
98
|
+
@d << {:name => '1'}
|
99
|
+
@db.transaction(:savepoint=>true) do
|
100
|
+
@d << {:name => '2'}
|
101
|
+
@db.table_exists?(:asadf098asd9asd98sa).must_equal false
|
102
|
+
@d << {:name => '3'}
|
103
|
+
end
|
104
|
+
@d << {:name => '4'}
|
105
|
+
end
|
106
|
+
@d.select_order_map(:name).must_equal %w'1 2 3 4'
|
107
|
+
end
|
108
|
+
|
87
109
|
it "should support nested transactions through savepoints using the savepoint option" do
|
88
110
|
@db.transaction do
|
89
111
|
@d << {:name => '1'}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.29.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -229,6 +229,7 @@ extra_rdoc_files:
|
|
229
229
|
- doc/release_notes/4.26.0.txt
|
230
230
|
- doc/release_notes/4.27.0.txt
|
231
231
|
- doc/release_notes/4.28.0.txt
|
232
|
+
- doc/release_notes/4.29.0.txt
|
232
233
|
files:
|
233
234
|
- CHANGELOG
|
234
235
|
- MIT-LICENSE
|
@@ -345,6 +346,7 @@ files:
|
|
345
346
|
- doc/release_notes/4.26.0.txt
|
346
347
|
- doc/release_notes/4.27.0.txt
|
347
348
|
- doc/release_notes/4.28.0.txt
|
349
|
+
- doc/release_notes/4.29.0.txt
|
348
350
|
- doc/release_notes/4.3.0.txt
|
349
351
|
- doc/release_notes/4.4.0.txt
|
350
352
|
- doc/release_notes/4.5.0.txt
|
@@ -598,6 +600,7 @@ files:
|
|
598
600
|
- lib/sequel/plugins/update_or_create.rb
|
599
601
|
- lib/sequel/plugins/update_primary_key.rb
|
600
602
|
- lib/sequel/plugins/update_refresh.rb
|
603
|
+
- lib/sequel/plugins/uuid.rb
|
601
604
|
- lib/sequel/plugins/validate_associated.rb
|
602
605
|
- lib/sequel/plugins/validation_class_methods.rb
|
603
606
|
- lib/sequel/plugins/validation_helpers.rb
|
@@ -755,6 +758,7 @@ files:
|
|
755
758
|
- spec/extensions/update_or_create_spec.rb
|
756
759
|
- spec/extensions/update_primary_key_spec.rb
|
757
760
|
- spec/extensions/update_refresh_spec.rb
|
761
|
+
- spec/extensions/uuid_spec.rb
|
758
762
|
- spec/extensions/validate_associated_spec.rb
|
759
763
|
- spec/extensions/validation_class_methods_spec.rb
|
760
764
|
- spec/extensions/validation_helpers_spec.rb
|