sequel 4.28.0 → 4.29.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.
- 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
|