sequel 4.39.0 → 4.40.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +34 -0
  3. data/README.rdoc +8 -4
  4. data/doc/active_record.rdoc +1 -1
  5. data/doc/advanced_associations.rdoc +7 -7
  6. data/doc/association_basics.rdoc +7 -7
  7. data/doc/cheat_sheet.rdoc +5 -3
  8. data/doc/core_extensions.rdoc +3 -3
  9. data/doc/dataset_filtering.rdoc +1 -1
  10. data/doc/object_model.rdoc +16 -7
  11. data/doc/postgresql.rdoc +3 -3
  12. data/doc/querying.rdoc +3 -3
  13. data/doc/release_notes/4.40.0.txt +179 -0
  14. data/doc/security.rdoc +2 -1
  15. data/doc/sql.rdoc +34 -18
  16. data/doc/testing.rdoc +1 -0
  17. data/doc/virtual_rows.rdoc +11 -2
  18. data/lib/sequel/adapters/jdbc/derby.rb +7 -1
  19. data/lib/sequel/adapters/jdbc/h2.rb +15 -1
  20. data/lib/sequel/adapters/oracle.rb +9 -5
  21. data/lib/sequel/adapters/postgres.rb +0 -1
  22. data/lib/sequel/adapters/shared/cubrid.rb +11 -11
  23. data/lib/sequel/adapters/shared/db2.rb +4 -8
  24. data/lib/sequel/adapters/shared/mssql.rb +41 -28
  25. data/lib/sequel/adapters/shared/mysql.rb +9 -6
  26. data/lib/sequel/adapters/shared/oracle.rb +16 -5
  27. data/lib/sequel/adapters/shared/postgres.rb +84 -45
  28. data/lib/sequel/adapters/shared/sqlanywhere.rb +29 -15
  29. data/lib/sequel/adapters/shared/sqlite.rb +6 -6
  30. data/lib/sequel/core.rb +61 -10
  31. data/lib/sequel/database/connecting.rb +2 -1
  32. data/lib/sequel/database/features.rb +7 -0
  33. data/lib/sequel/database/query.rb +1 -1
  34. data/lib/sequel/database/schema_methods.rb +30 -3
  35. data/lib/sequel/database/transactions.rb +4 -2
  36. data/lib/sequel/dataset/actions.rb +1 -1
  37. data/lib/sequel/dataset/graph.rb +6 -1
  38. data/lib/sequel/dataset/query.rb +14 -7
  39. data/lib/sequel/dataset/sql.rb +2 -2
  40. data/lib/sequel/extensions/core_extensions.rb +2 -1
  41. data/lib/sequel/extensions/pg_row.rb +2 -2
  42. data/lib/sequel/extensions/s.rb +57 -0
  43. data/lib/sequel/extensions/set_overrides.rb +5 -1
  44. data/lib/sequel/extensions/sql_expr.rb +1 -0
  45. data/lib/sequel/extensions/symbol_aref.rb +71 -0
  46. data/lib/sequel/extensions/symbol_aref_refinement.rb +41 -0
  47. data/lib/sequel/extensions/symbol_as.rb +23 -0
  48. data/lib/sequel/extensions/symbol_as_refinement.rb +35 -0
  49. data/lib/sequel/model/base.rb +3 -3
  50. data/lib/sequel/plugins/class_table_inheritance.rb +14 -3
  51. data/lib/sequel/plugins/column_select.rb +4 -2
  52. data/lib/sequel/plugins/dataset_associations.rb +12 -4
  53. data/lib/sequel/plugins/insert_returning_select.rb +1 -1
  54. data/lib/sequel/plugins/mssql_optimistic_locking.rb +1 -1
  55. data/lib/sequel/plugins/prepared_statements.rb +1 -0
  56. data/lib/sequel/sql.rb +40 -8
  57. data/lib/sequel/version.rb +1 -1
  58. data/spec/adapters/firebird_spec.rb +3 -3
  59. data/spec/adapters/mssql_spec.rb +40 -40
  60. data/spec/adapters/mysql_spec.rb +5 -5
  61. data/spec/adapters/oracle_spec.rb +4 -4
  62. data/spec/adapters/postgres_spec.rb +135 -124
  63. data/spec/adapters/spec_helper.rb +1 -0
  64. data/spec/adapters/sqlite_spec.rb +6 -6
  65. data/spec/core/dataset_spec.rb +2 -2
  66. data/spec/core/expression_filters_spec.rb +43 -2
  67. data/spec/core/schema_spec.rb +35 -1
  68. data/spec/core_extensions_spec.rb +27 -0
  69. data/spec/extensions/class_table_inheritance_spec.rb +8 -0
  70. data/spec/extensions/column_select_spec.rb +8 -0
  71. data/spec/extensions/core_refinements_spec.rb +1 -1
  72. data/spec/extensions/dataset_associations_spec.rb +9 -0
  73. data/spec/extensions/insert_returning_select_spec.rb +20 -0
  74. data/spec/extensions/prepared_statements_spec.rb +7 -0
  75. data/spec/extensions/s_spec.rb +60 -0
  76. data/spec/extensions/symbol_aref_refinement_spec.rb +28 -0
  77. data/spec/extensions/symbol_as_refinement_spec.rb +21 -0
  78. data/spec/integration/associations_test.rb +62 -57
  79. data/spec/integration/dataset_test.rb +54 -54
  80. data/spec/integration/eager_loader_test.rb +7 -7
  81. data/spec/integration/plugin_test.rb +20 -20
  82. data/spec/integration/prepared_statement_test.rb +1 -1
  83. data/spec/integration/schema_test.rb +21 -0
  84. data/spec/integration/spec_helper.rb +1 -0
  85. 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 :col___alias" do
313
- DB.literal(:c___a).must_equal "`c` AS 'a'"
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 :table__col___alias" do
317
- DB.literal(:t__c___a).must_equal "`t`.`c` AS 'a'"
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(:c___a).sql.must_equal "SELECT `c` AS 'a' FROM `t`"
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[:t___a].sql.must_equal "SELECT * FROM `t` AS 'a'"
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
@@ -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
@@ -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
+