sequel 4.39.0 → 4.40.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +34 -0
- data/README.rdoc +8 -4
- data/doc/active_record.rdoc +1 -1
- data/doc/advanced_associations.rdoc +7 -7
- data/doc/association_basics.rdoc +7 -7
- data/doc/cheat_sheet.rdoc +5 -3
- data/doc/core_extensions.rdoc +3 -3
- data/doc/dataset_filtering.rdoc +1 -1
- data/doc/object_model.rdoc +16 -7
- data/doc/postgresql.rdoc +3 -3
- data/doc/querying.rdoc +3 -3
- data/doc/release_notes/4.40.0.txt +179 -0
- data/doc/security.rdoc +2 -1
- data/doc/sql.rdoc +34 -18
- data/doc/testing.rdoc +1 -0
- data/doc/virtual_rows.rdoc +11 -2
- data/lib/sequel/adapters/jdbc/derby.rb +7 -1
- data/lib/sequel/adapters/jdbc/h2.rb +15 -1
- data/lib/sequel/adapters/oracle.rb +9 -5
- data/lib/sequel/adapters/postgres.rb +0 -1
- data/lib/sequel/adapters/shared/cubrid.rb +11 -11
- data/lib/sequel/adapters/shared/db2.rb +4 -8
- data/lib/sequel/adapters/shared/mssql.rb +41 -28
- data/lib/sequel/adapters/shared/mysql.rb +9 -6
- data/lib/sequel/adapters/shared/oracle.rb +16 -5
- data/lib/sequel/adapters/shared/postgres.rb +84 -45
- data/lib/sequel/adapters/shared/sqlanywhere.rb +29 -15
- data/lib/sequel/adapters/shared/sqlite.rb +6 -6
- data/lib/sequel/core.rb +61 -10
- data/lib/sequel/database/connecting.rb +2 -1
- data/lib/sequel/database/features.rb +7 -0
- data/lib/sequel/database/query.rb +1 -1
- data/lib/sequel/database/schema_methods.rb +30 -3
- data/lib/sequel/database/transactions.rb +4 -2
- data/lib/sequel/dataset/actions.rb +1 -1
- data/lib/sequel/dataset/graph.rb +6 -1
- data/lib/sequel/dataset/query.rb +14 -7
- data/lib/sequel/dataset/sql.rb +2 -2
- data/lib/sequel/extensions/core_extensions.rb +2 -1
- data/lib/sequel/extensions/pg_row.rb +2 -2
- data/lib/sequel/extensions/s.rb +57 -0
- data/lib/sequel/extensions/set_overrides.rb +5 -1
- data/lib/sequel/extensions/sql_expr.rb +1 -0
- data/lib/sequel/extensions/symbol_aref.rb +71 -0
- data/lib/sequel/extensions/symbol_aref_refinement.rb +41 -0
- data/lib/sequel/extensions/symbol_as.rb +23 -0
- data/lib/sequel/extensions/symbol_as_refinement.rb +35 -0
- data/lib/sequel/model/base.rb +3 -3
- data/lib/sequel/plugins/class_table_inheritance.rb +14 -3
- data/lib/sequel/plugins/column_select.rb +4 -2
- data/lib/sequel/plugins/dataset_associations.rb +12 -4
- data/lib/sequel/plugins/insert_returning_select.rb +1 -1
- data/lib/sequel/plugins/mssql_optimistic_locking.rb +1 -1
- data/lib/sequel/plugins/prepared_statements.rb +1 -0
- data/lib/sequel/sql.rb +40 -8
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/firebird_spec.rb +3 -3
- data/spec/adapters/mssql_spec.rb +40 -40
- data/spec/adapters/mysql_spec.rb +5 -5
- data/spec/adapters/oracle_spec.rb +4 -4
- data/spec/adapters/postgres_spec.rb +135 -124
- data/spec/adapters/spec_helper.rb +1 -0
- data/spec/adapters/sqlite_spec.rb +6 -6
- data/spec/core/dataset_spec.rb +2 -2
- data/spec/core/expression_filters_spec.rb +43 -2
- data/spec/core/schema_spec.rb +35 -1
- data/spec/core_extensions_spec.rb +27 -0
- data/spec/extensions/class_table_inheritance_spec.rb +8 -0
- data/spec/extensions/column_select_spec.rb +8 -0
- data/spec/extensions/core_refinements_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +9 -0
- data/spec/extensions/insert_returning_select_spec.rb +20 -0
- data/spec/extensions/prepared_statements_spec.rb +7 -0
- data/spec/extensions/s_spec.rb +60 -0
- data/spec/extensions/symbol_aref_refinement_spec.rb +28 -0
- data/spec/extensions/symbol_as_refinement_spec.rb +21 -0
- data/spec/integration/associations_test.rb +62 -57
- data/spec/integration/dataset_test.rb +54 -54
- data/spec/integration/eager_loader_test.rb +7 -7
- data/spec/integration/plugin_test.rb +20 -20
- data/spec/integration/prepared_statement_test.rb +1 -1
- data/spec/integration/schema_test.rb +21 -0
- data/spec/integration/spec_helper.rb +1 -0
- metadata +12 -2
@@ -15,6 +15,7 @@ begin
|
|
15
15
|
rescue LoadError
|
16
16
|
end
|
17
17
|
|
18
|
+
Sequel.split_symbols = false if ENV['SEQUEL_NO_SPLIT_SYMBOLS']
|
18
19
|
Sequel::Database.extension :duplicate_column_handler if ENV['SEQUEL_DUPLICATE_COLUMN_HANDLER']
|
19
20
|
Sequel::Database.extension :columns_introspection if ENV['SEQUEL_COLUMNS_INTROSPECTION']
|
20
21
|
Sequel::Model.cache_associations = false if ENV['SEQUEL_NO_CACHE_ASSOCIATIONS']
|
@@ -309,12 +309,12 @@ describe "An SQLite dataset" do
|
|
309
309
|
end
|
310
310
|
|
311
311
|
describe "An SQLite dataset AS clause" do
|
312
|
-
it "should use a string literal for :
|
313
|
-
DB.literal(:
|
312
|
+
it "should use a string literal for Sequel[:col].as(:alias)" do
|
313
|
+
DB.literal(Sequel[:c].as(:a)).must_equal "`c` AS 'a'"
|
314
314
|
end
|
315
315
|
|
316
|
-
it "should use a string literal for :
|
317
|
-
DB.literal(:
|
316
|
+
it "should use a string literal for Sequel[:table][:col].as(:alias)" do
|
317
|
+
DB.literal(Sequel[:t][:c].as(:a)).must_equal "`t`.`c` AS 'a'"
|
318
318
|
end
|
319
319
|
|
320
320
|
it "should use a string literal for :column.as(:alias)" do
|
@@ -322,11 +322,11 @@ describe "An SQLite dataset AS clause" do
|
|
322
322
|
end
|
323
323
|
|
324
324
|
it "should use a string literal in the SELECT clause" do
|
325
|
-
DB[:t].select(:
|
325
|
+
DB[:t].select(Sequel[:c].as(:a)).sql.must_equal "SELECT `c` AS 'a' FROM `t`"
|
326
326
|
end
|
327
327
|
|
328
328
|
it "should use a string literal in the FROM clause" do
|
329
|
-
DB[:
|
329
|
+
DB[Sequel[:t].as(:a)].sql.must_equal "SELECT * FROM `t` AS 'a'"
|
330
330
|
end
|
331
331
|
|
332
332
|
it "should use a string literal in the JOIN clause" do
|
data/spec/core/dataset_spec.rb
CHANGED
@@ -5108,13 +5108,13 @@ describe "Dataset emulated complex expression operators" do
|
|
5108
5108
|
it "should emulate >>" do
|
5109
5109
|
@ds.literal(Sequel::SQL::NumericExpression.new(:>>, @n)).must_equal "x"
|
5110
5110
|
@ds.literal(@n >> 1).must_equal "(x / power(2, 1))"
|
5111
|
-
@ds.literal(@n >> 1 >> 2).must_equal "(x / power(2, 1) / power(2, 2))"
|
5111
|
+
@ds.literal(@n >> 1 >> 2).must_equal "((x / power(2, 1)) / power(2, 2))"
|
5112
5112
|
end
|
5113
5113
|
|
5114
5114
|
it "should emulate <<" do
|
5115
5115
|
@ds.literal(Sequel::SQL::NumericExpression.new(:<<, @n)).must_equal "x"
|
5116
5116
|
@ds.literal(@n << 1).must_equal "(x * power(2, 1))"
|
5117
|
-
@ds.literal(@n << 1 << 2).must_equal "(x * power(2, 1) * power(2, 2))"
|
5117
|
+
@ds.literal(@n << 1 << 2).must_equal "((x * power(2, 1)) * power(2, 2))"
|
5118
5118
|
end
|
5119
5119
|
|
5120
5120
|
it "should emulate B~" do
|
@@ -16,8 +16,26 @@ describe "Blockless Ruby Filters" do
|
|
16
16
|
@d.l(:x).must_equal 'x'
|
17
17
|
end
|
18
18
|
|
19
|
-
it "should support qualified columns" do
|
19
|
+
it "should support qualified columns and aliased columns using symbols" do
|
20
20
|
@d.l(:x__y).must_equal 'x.y'
|
21
|
+
@d.l(:x___y).must_equal 'x AS y'
|
22
|
+
@d.l(:x__y___z).must_equal 'x.y AS z'
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should support qualified columns using virtual rows" do
|
26
|
+
@d.l(Sequel.expr{x__y}).must_equal 'x.y'
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should not split symbols or virtual row methods if symbol splitting is disabled" do
|
30
|
+
begin
|
31
|
+
Sequel.split_symbols = false
|
32
|
+
@d.l(:x__y).must_equal 'x__y'
|
33
|
+
@d.l(:x___y).must_equal 'x___y'
|
34
|
+
@d.l(:x__y___z).must_equal 'x__y___z'
|
35
|
+
@d.l(Sequel.expr{x__y}).must_equal 'x__y'
|
36
|
+
ensure
|
37
|
+
Sequel.split_symbols = true
|
38
|
+
end
|
21
39
|
end
|
22
40
|
|
23
41
|
it "should support NOT with SQL functions" do
|
@@ -129,6 +147,21 @@ describe "Blockless Ruby Filters" do
|
|
129
147
|
proc{~Sequel.expr(:x).sql_string}.must_raise(NoMethodError)
|
130
148
|
end
|
131
149
|
|
150
|
+
it "should only allow combining associative operators" do
|
151
|
+
@d.lit(Sequel.expr{a + b + c}).must_equal '(a + b + c)'
|
152
|
+
@d.lit(Sequel.expr{a - b - c}).must_equal '((a - b) - c)'
|
153
|
+
@d.lit(Sequel.expr{a * b * c}).must_equal '(a * b * c)'
|
154
|
+
@d.lit(Sequel.expr{a / b / c}).must_equal '((a / b) / c)'
|
155
|
+
@d.lit(Sequel.expr{a & b & c}).must_equal '(a AND b AND c)'
|
156
|
+
@d.lit(Sequel.expr{a | b | c}).must_equal '(a OR b OR c)'
|
157
|
+
@d.lit(Sequel.expr{a.sql_string + b + c}).must_equal '(a || b || c)'
|
158
|
+
@d.lit(Sequel.expr{a.sql_number >> b >> c}).must_equal '((a >> b) >> c)'
|
159
|
+
@d.lit(Sequel.expr{a.sql_number << b << c}).must_equal '((a << b) << c)'
|
160
|
+
@d.lit(Sequel.expr{a.sql_number % b % c}).must_equal '((a % b) % c)'
|
161
|
+
@d.lit(Sequel.expr{a.sql_number & b & c}).must_equal '(a & b & c)'
|
162
|
+
@d.lit(Sequel.expr{a.sql_number | b | c}).must_equal '(a | b | c)'
|
163
|
+
end
|
164
|
+
|
132
165
|
it "should allow mathematical or string operations on true, false, or nil" do
|
133
166
|
@d.lit(Sequel.expr(:x) + 1).must_equal '(x + 1)'
|
134
167
|
@d.lit(Sequel.expr(:x) - true).must_equal "(x - 't')"
|
@@ -206,7 +239,7 @@ describe "Blockless Ruby Filters" do
|
|
206
239
|
@d.l((Sequel.lit('x') * :y) < 100.01).must_equal '((x * y) < 100.01)'
|
207
240
|
@d.l((Sequel.lit('x') ** :y) < 100.01).must_equal '(power(x, y) < 100.01)'
|
208
241
|
@d.l((Sequel.lit('x') - Sequel.expr(:y)/2) >= 100000000000000000000000000000000000).must_equal '((x - (y / 2)) >= 100000000000000000000000000000000000)'
|
209
|
-
@d.l((Sequel.lit('z') * ((Sequel.lit('x') / :y)/(Sequel.expr(:x) + :y))) <= 100).must_equal '((z * (x / y / (x + y))) <= 100)'
|
242
|
+
@d.l((Sequel.lit('z') * ((Sequel.lit('x') / :y)/(Sequel.expr(:x) + :y))) <= 100).must_equal '((z * ((x / y) / (x + y))) <= 100)'
|
210
243
|
@d.l(~((((Sequel.lit('x') - :y)/(Sequel.expr(:x) + :y))*:z) <= 100)).must_equal '((((x - y) / (x + y)) * z) > 100)'
|
211
244
|
end
|
212
245
|
|
@@ -921,6 +954,14 @@ describe "Sequel core extension replacements" do
|
|
921
954
|
l(Sequel.qualify(:t, :c), "t.c")
|
922
955
|
end
|
923
956
|
|
957
|
+
it "Sequel::SQL::Identifier#[] should return a qualified identifier" do
|
958
|
+
l(Sequel[:t][:c], "t.c")
|
959
|
+
end
|
960
|
+
|
961
|
+
it "Sequel::SQL::QualifiedIdentifier#[] should return a nested qualified identifier" do
|
962
|
+
l(Sequel[:s][:t][:c], "s.t.c")
|
963
|
+
end
|
964
|
+
|
924
965
|
it "Sequel.identifier should return an identifier" do
|
925
966
|
l(Sequel.identifier(:t__c), "t__c")
|
926
967
|
end
|
data/spec/core/schema_spec.rb
CHANGED
@@ -12,10 +12,11 @@ describe "DB#create_table" do
|
|
12
12
|
|
13
13
|
it "should accept the table name in multiple formats" do
|
14
14
|
@db.create_table(:cats__cats) {}
|
15
|
+
@db.create_table(Sequel[:cats][:cats]) {}
|
15
16
|
@db.create_table("cats__cats1") {}
|
16
17
|
@db.create_table(Sequel.identifier(:cats__cats2)) {}
|
17
18
|
@db.create_table(Sequel.qualify(:cats3, :cats)) {}
|
18
|
-
@db.sqls.must_equal ['CREATE TABLE cats.cats ()', 'CREATE TABLE cats__cats1 ()', 'CREATE TABLE cats__cats2 ()', 'CREATE TABLE cats3.cats ()']
|
19
|
+
@db.sqls.must_equal ['CREATE TABLE cats.cats ()', 'CREATE TABLE cats.cats ()', 'CREATE TABLE cats__cats1 ()', 'CREATE TABLE cats__cats2 ()', 'CREATE TABLE cats3.cats ()']
|
19
20
|
end
|
20
21
|
|
21
22
|
it "should raise an error if the table name argument is not valid" do
|
@@ -132,6 +133,23 @@ describe "DB#create_table" do
|
|
132
133
|
@db.sqls.must_equal ['CREATE TABLE cats (id integer CONSTRAINT foo PRIMARY KEY AUTOINCREMENT)']
|
133
134
|
end
|
134
135
|
|
136
|
+
it "should automatically set primary key column NOT NULL if database doesn't do it automatically" do
|
137
|
+
def @db.can_add_primary_key_constraint_on_nullable_columns?; false end
|
138
|
+
@db.create_table(:cats) do
|
139
|
+
primary_key :id
|
140
|
+
end
|
141
|
+
@db.sqls.must_equal ['CREATE TABLE cats (id integer NOT NULL PRIMARY KEY AUTOINCREMENT)']
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should automatically set primary key column NOT NULL when adding constraint if database doesn't do it automatically" do
|
145
|
+
def @db.can_add_primary_key_constraint_on_nullable_columns?; false end
|
146
|
+
@db.create_table(:cats) do
|
147
|
+
String :id
|
148
|
+
primary_key [:id]
|
149
|
+
end
|
150
|
+
@db.sqls.must_equal ['CREATE TABLE cats (id varchar(255) NOT NULL, PRIMARY KEY (id))']
|
151
|
+
end
|
152
|
+
|
135
153
|
it "should handling splitting named column constraints into table constraints if unsupported" do
|
136
154
|
def @db.supports_named_column_constraints?; false end
|
137
155
|
@db.create_table(:cats) do
|
@@ -1100,6 +1118,22 @@ describe "DB#alter_table" do
|
|
1100
1118
|
@db.sqls.must_equal ["ALTER TABLE cats ADD CONSTRAINT cpk PRIMARY KEY (id, type)"]
|
1101
1119
|
end
|
1102
1120
|
|
1121
|
+
it "should set primary key column NOT NULL when using add_primary_key if database doesn't handle it" do
|
1122
|
+
def @db.can_add_primary_key_constraint_on_nullable_columns?; false end
|
1123
|
+
@db.alter_table(:cats) do
|
1124
|
+
add_primary_key :id
|
1125
|
+
end
|
1126
|
+
@db.sqls.must_equal ["ALTER TABLE cats ADD COLUMN id integer NOT NULL PRIMARY KEY AUTOINCREMENT"]
|
1127
|
+
end
|
1128
|
+
|
1129
|
+
it "should set primary key column NOT NULL when adding primary key constraint if database doesn't handle it" do
|
1130
|
+
def @db.can_add_primary_key_constraint_on_nullable_columns?; false end
|
1131
|
+
@db.alter_table(:cats) do
|
1132
|
+
add_primary_key [:id, :type]
|
1133
|
+
end
|
1134
|
+
@db.sqls.must_equal ["ALTER TABLE cats ALTER COLUMN id SET NOT NULL", "ALTER TABLE cats ALTER COLUMN type SET NOT NULL", "ALTER TABLE cats ADD PRIMARY KEY (id, type)"]
|
1135
|
+
end
|
1136
|
+
|
1103
1137
|
it "should support drop_column" do
|
1104
1138
|
@db.alter_table(:cats) do
|
1105
1139
|
drop_column :score
|
@@ -21,6 +21,7 @@ Sequel.extension :core_extensions
|
|
21
21
|
if RUBY_VERSION < '1.9.0'
|
22
22
|
Sequel.extension :ruby18_symbol_extensions
|
23
23
|
end
|
24
|
+
Sequel.extension :symbol_aref
|
24
25
|
|
25
26
|
require 'minitest/autorun'
|
26
27
|
|
@@ -702,3 +703,29 @@ describe "Postgres extensions integration" do
|
|
702
703
|
@db.literal((1..2).pg_range(:int4range)).must_equal "int4range(1,2,'[]')"
|
703
704
|
end
|
704
705
|
end
|
706
|
+
|
707
|
+
describe "symbol_aref extensions" do
|
708
|
+
before do
|
709
|
+
@db = Sequel.mock
|
710
|
+
end
|
711
|
+
|
712
|
+
it "Symbol#[] should create qualified identifier if given a symbol" do
|
713
|
+
@db.literal(:x[:y]).must_equal "x.y"
|
714
|
+
end
|
715
|
+
|
716
|
+
it "Symbol#[] should create qualified identifier if given an identifier" do
|
717
|
+
@db.literal(:x[Sequel[:y]]).must_equal "x.y"
|
718
|
+
end
|
719
|
+
|
720
|
+
it "Symbol#[] should create qualified identifier if given a qualified identifier" do
|
721
|
+
@db.literal(:x[:y[:z]]).must_equal "x.y.z"
|
722
|
+
end
|
723
|
+
|
724
|
+
it "should not affect other arguments to Symbol#[]" do
|
725
|
+
if RUBY_VERSION >= '1.9'
|
726
|
+
:x[0].must_equal "x"
|
727
|
+
else
|
728
|
+
@db.literal(:x[0]).must_equal "x(0)"
|
729
|
+
end
|
730
|
+
end
|
731
|
+
end
|
@@ -51,6 +51,14 @@ describe "class_table_inheritance plugin" do
|
|
51
51
|
Object.send(:remove_const, :Employee)
|
52
52
|
end
|
53
53
|
|
54
|
+
it "should not attempt to use prepared statements" do
|
55
|
+
Manager.plugin :prepared_statements
|
56
|
+
Manager[1]
|
57
|
+
@db.sqls.must_equal ["SELECT employees.id, employees.name, employees.kind, managers.num_staff FROM employees INNER JOIN managers ON (managers.id = employees.id) WHERE (managers.id = 1) LIMIT 1"]
|
58
|
+
Manager.load(:id=>1, :kind=>'Manager', :num_staff=>2).save
|
59
|
+
@db.sqls.must_equal ["UPDATE employees SET kind = 'Manager' WHERE (id = 1)", "UPDATE managers SET num_staff = 2 WHERE (id = 1)"]
|
60
|
+
end
|
61
|
+
|
54
62
|
it "#cti_base_model should be the model that loaded the plugin" do
|
55
63
|
Executive.cti_base_model.must_equal Employee
|
56
64
|
end
|
@@ -98,6 +98,14 @@ describe "Sequel::Plugins::ColumnSelect" do
|
|
98
98
|
@Album.dataset.sql.must_equal 'SELECT albums.id, albums.a, albums.b, albums.c FROM albums'
|
99
99
|
end
|
100
100
|
|
101
|
+
it "should handle case where schema parsing and columns does not produce results" do
|
102
|
+
def @db.supports_schema_parsing?() true end
|
103
|
+
def @db.schema_parse_table(t, *) [] end
|
104
|
+
@db.extend_datasets{def columns; raise Sequel::DatabaseError; end}
|
105
|
+
@Album.plugin :column_select
|
106
|
+
@Album.dataset.sql.must_equal 'SELECT * FROM albums'
|
107
|
+
end
|
108
|
+
|
101
109
|
it "works correctly when loaded on model without a dataset" do
|
102
110
|
c = Class.new(Sequel::Model)
|
103
111
|
c.plugin :column_select
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
2
|
|
3
|
-
if RUBY_VERSION >= '2.0.0' && RUBY_ENGINE == 'ruby'
|
3
|
+
if (RUBY_VERSION >= '2.0.0' && RUBY_ENGINE == 'ruby') # || (RUBY_VERSION >= '2.3.0' && RUBY_ENGINE == 'jruby')
|
4
4
|
Sequel.extension :core_refinements, :pg_array, :pg_hstore, :pg_row, :pg_range, :pg_row_ops, :pg_range_ops, :pg_array_ops, :pg_hstore_ops, :pg_json, :pg_json_ops
|
5
5
|
using Sequel::CoreRefinements
|
6
6
|
|
@@ -26,6 +26,7 @@ describe "Sequel::Plugins::DatasetAssociations" do
|
|
26
26
|
@Album.columns :id, :name, :artist_id
|
27
27
|
@Tag.columns :id, :name
|
28
28
|
|
29
|
+
@Album.plugin :many_through_many
|
29
30
|
@Artist.plugin :many_through_many
|
30
31
|
@Artist.plugin :pg_array_associations
|
31
32
|
@Tag.plugin :pg_array_associations
|
@@ -33,6 +34,7 @@ describe "Sequel::Plugins::DatasetAssociations" do
|
|
33
34
|
@Artist.one_to_one :first_album, :class=>@Album
|
34
35
|
@Album.many_to_one :artist, :class=>@Artist
|
35
36
|
@Album.many_to_many :tags, :class=>@Tag
|
37
|
+
@Album.many_through_many :mthm_tags, [[:albums_tags, :album_id, :tag_id]], :class=>@Tag
|
36
38
|
@Album.one_through_one :first_tag, :class=>@Tag, :right_key=>:tag_id
|
37
39
|
@Tag.many_to_many :albums, :class=>@Album
|
38
40
|
@Artist.pg_array_to_many :artist_tags, :class=>@Tag, :key=>:tag_ids
|
@@ -83,6 +85,13 @@ describe "Sequel::Plugins::DatasetAssociations" do
|
|
83
85
|
ds.sql.must_equal "SELECT tags.* FROM tags WHERE (tags.id IN (SELECT albums_tags.tag_id FROM artists INNER JOIN albums ON (albums.artist_id = artists.id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) INNER JOIN tags ON (tags.id = albums_tags.tag_id) WHERE (albums.artist_id IN (SELECT artists.id FROM artists))))"
|
84
86
|
end
|
85
87
|
|
88
|
+
it "should work for many_through_many associations with a single join table" do
|
89
|
+
ds = @Album.mthm_tags
|
90
|
+
ds.must_be_kind_of(Sequel::Dataset)
|
91
|
+
ds.model.must_equal @Tag
|
92
|
+
ds.sql.must_equal "SELECT tags.* FROM tags WHERE (tags.id IN (SELECT albums_tags.tag_id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) WHERE (albums_tags.album_id IN (SELECT albums.id FROM albums))))"
|
93
|
+
end
|
94
|
+
|
86
95
|
it "should work for one_through_many associations" do
|
87
96
|
ds = @Artist.otags
|
88
97
|
ds.must_be_kind_of(Sequel::Dataset)
|
@@ -12,6 +12,26 @@ describe "Sequel::Plugins::InsertReturningSelect" do
|
|
12
12
|
@db.sqls
|
13
13
|
end
|
14
14
|
|
15
|
+
it "should work if loaded into a model without a dataset that also uses the lazy_attributes or dataset associations plugins" do
|
16
|
+
c = Sequel::Model(@db)
|
17
|
+
c.plugin :insert_returning_select
|
18
|
+
c.columns :id, :x
|
19
|
+
c.plugin :lazy_attributes
|
20
|
+
c.plugin :dataset_associations
|
21
|
+
|
22
|
+
c.set_dataset @db[:albums].select(:id, :x)
|
23
|
+
c.plugin :lazy_attributes, :x
|
24
|
+
c.many_to_one :c, :key=>:id, :class=>c
|
25
|
+
@db.sqls
|
26
|
+
|
27
|
+
c.dataset.sql.must_equal 'SELECT id FROM albums'
|
28
|
+
c.create(:x=>2)
|
29
|
+
@db.sqls.must_equal ['INSERT INTO albums (x) VALUES (2) RETURNING id']
|
30
|
+
c.load(:id=>2).x
|
31
|
+
@db.sqls.must_equal ['SELECT albums.x FROM albums WHERE (id = 2) LIMIT 1']
|
32
|
+
c.dataset.cs.sql.must_equal "SELECT id FROM albums WHERE (albums.id IN (SELECT albums.id FROM albums))"
|
33
|
+
end
|
34
|
+
|
15
35
|
it "should add a returning clause when inserting using selected columns" do
|
16
36
|
@Album.plugin :insert_returning_select
|
17
37
|
@Album.create(:x=>2).must_equal @Album.load(:id=>1, :x=>2)
|
@@ -17,6 +17,13 @@ describe "prepared_statements plugin" do
|
|
17
17
|
@db.sqls.must_equal ["SELECT id, name, i FROM people WHERE (id = 1) LIMIT 1 -- read_only"]
|
18
18
|
end
|
19
19
|
|
20
|
+
it "should correctly lookup by primary key for joined dataset" do
|
21
|
+
@c.dataset = @c.dataset.from(:people, :people2)
|
22
|
+
@db.sqls
|
23
|
+
@c[1].must_equal @p
|
24
|
+
@db.sqls.must_equal ["SELECT * FROM people, people2 WHERE (people.id = 1) LIMIT 1 -- read_only"]
|
25
|
+
end
|
26
|
+
|
20
27
|
prepared_statements_spec = shared_description do
|
21
28
|
it "should correctly delete instance" do
|
22
29
|
@p.destroy.must_equal @p
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
|
+
|
3
|
+
Sequel.extension :s
|
4
|
+
|
5
|
+
describe "s extension as refinement" do
|
6
|
+
include Sequel::S
|
7
|
+
|
8
|
+
before do
|
9
|
+
@db = Sequel.mock
|
10
|
+
end
|
11
|
+
|
12
|
+
it "S should be callable with different arguments" do
|
13
|
+
@db.literal(S(:s) + 1).must_equal "(s + 1)"
|
14
|
+
@db.literal(S('s') + '1').must_equal "('s' || '1')"
|
15
|
+
@db.literal(~S([[:s, 1], [:z, 2]])).must_equal "((s != 1) OR (z != 2))"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "S should be callable with blocks" do
|
19
|
+
@db.literal(S{x + 1}).must_equal "(x + 1)"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "S should raise an error if called with multiple objects" do
|
23
|
+
proc{S(:x, 1)}.must_raise ArgumentError
|
24
|
+
end
|
25
|
+
|
26
|
+
it "S should raise an error if called with objects and block" do
|
27
|
+
proc{S(:x){}}.must_raise Sequel::Error
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
if (RUBY_VERSION >= '2.0.0' && RUBY_ENGINE == 'ruby') # || (RUBY_VERSION >= '2.3.0' && RUBY_ENGINE == 'jruby')
|
33
|
+
using Sequel::S
|
34
|
+
|
35
|
+
describe "s extension as refinement" do
|
36
|
+
before do
|
37
|
+
@db = Sequel.mock
|
38
|
+
end
|
39
|
+
|
40
|
+
it "S should be callable with different arguments" do
|
41
|
+
@db.literal(S(:s) + 1).must_equal "(s + 1)"
|
42
|
+
@db.literal(S('s') + '1').must_equal "('s' || '1')"
|
43
|
+
@db.literal(~S([[:s, 1], [:z, 2]])).must_equal "((s != 1) OR (z != 2))"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "S should be callable with blocks" do
|
47
|
+
@db.literal(S{x + 1}).must_equal "(x + 1)"
|
48
|
+
end
|
49
|
+
|
50
|
+
it "S should raise an error if called with multiple objects" do
|
51
|
+
proc{S(:x, 1)}.must_raise ArgumentError
|
52
|
+
end
|
53
|
+
|
54
|
+
it "S should raise an error if called with objects and block" do
|
55
|
+
proc{S(:x){}}.must_raise Sequel::Error
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
|
+
|
3
|
+
if (RUBY_VERSION >= '2.0.0' && RUBY_ENGINE == 'ruby') || (RUBY_VERSION >= '2.3.0' && RUBY_ENGINE == 'jruby')
|
4
|
+
Sequel.extension :symbol_aref_refinement
|
5
|
+
using Sequel::SymbolAref
|
6
|
+
|
7
|
+
describe "symbol_aref_refinement extension" do
|
8
|
+
before do
|
9
|
+
@db = Sequel.mock
|
10
|
+
end
|
11
|
+
|
12
|
+
it "Symbol#[] should create qualified identifier if given a symbol" do
|
13
|
+
@db.literal(:x[:y]).must_equal "x.y"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "Symbol#[] should create qualified identifier if given an identifier" do
|
17
|
+
@db.literal(:x[Sequel[:y]]).must_equal "x.y"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "Symbol#[] should create qualified identifier if given a qualified identifier" do
|
21
|
+
@db.literal(:x[:y[:z]]).must_equal "x.y.z"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should not affect other arguments to Symbol#[]" do
|
25
|
+
:x[0].must_equal "x"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
|
+
|
3
|
+
if (RUBY_VERSION >= '2.0.0' && RUBY_ENGINE == 'ruby') || (RUBY_VERSION >= '2.3.0' && RUBY_ENGINE == 'jruby')
|
4
|
+
Sequel.extension :symbol_as_refinement
|
5
|
+
using Sequel::SymbolAs
|
6
|
+
|
7
|
+
describe "symbol_as_refinement extension" do
|
8
|
+
before do
|
9
|
+
@db = Sequel.mock
|
10
|
+
end
|
11
|
+
|
12
|
+
it "Symbol#as should create aliased expression" do
|
13
|
+
@db.literal(:x.as(:y)).must_equal "x AS y"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "Symbol#as should create aliased expression with columns" do
|
17
|
+
@db.literal(:x.as(:y, [:c1, :c2])).must_equal "x AS y(c1, c2)"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|