sequel 4.45.0 → 4.46.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.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +108 -0
  3. data/doc/release_notes/4.46.0.txt +404 -0
  4. data/doc/security.rdoc +9 -0
  5. data/doc/sql.rdoc +2 -2
  6. data/doc/testing.rdoc +1 -1
  7. data/doc/validations.rdoc +1 -2
  8. data/lib/sequel/adapters/ado.rb +8 -3
  9. data/lib/sequel/adapters/ado/access.rb +8 -4
  10. data/lib/sequel/adapters/ado/mssql.rb +3 -1
  11. data/lib/sequel/adapters/amalgalite.rb +5 -0
  12. data/lib/sequel/adapters/cubrid.rb +16 -7
  13. data/lib/sequel/adapters/do.rb +7 -1
  14. data/lib/sequel/adapters/do/mysql.rb +8 -4
  15. data/lib/sequel/adapters/ibmdb.rb +10 -5
  16. data/lib/sequel/adapters/jdbc.rb +8 -2
  17. data/lib/sequel/adapters/jdbc/as400.rb +10 -3
  18. data/lib/sequel/adapters/jdbc/db2.rb +27 -16
  19. data/lib/sequel/adapters/jdbc/derby.rb +47 -20
  20. data/lib/sequel/adapters/jdbc/h2.rb +13 -7
  21. data/lib/sequel/adapters/jdbc/hsqldb.rb +18 -9
  22. data/lib/sequel/adapters/jdbc/mssql.rb +5 -2
  23. data/lib/sequel/adapters/jdbc/mysql.rb +3 -2
  24. data/lib/sequel/adapters/jdbc/oracle.rb +3 -2
  25. data/lib/sequel/adapters/jdbc/postgresql.rb +4 -3
  26. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +2 -1
  27. data/lib/sequel/adapters/jdbc/sqlite.rb +10 -3
  28. data/lib/sequel/adapters/jdbc/sqlserver.rb +23 -0
  29. data/lib/sequel/adapters/jdbc/transactions.rb +16 -10
  30. data/lib/sequel/adapters/mock.rb +5 -0
  31. data/lib/sequel/adapters/mysql.rb +8 -1
  32. data/lib/sequel/adapters/mysql2.rb +6 -1
  33. data/lib/sequel/adapters/odbc.rb +20 -8
  34. data/lib/sequel/adapters/odbc/mssql.rb +6 -3
  35. data/lib/sequel/adapters/oracle.rb +12 -6
  36. data/lib/sequel/adapters/postgres.rb +20 -8
  37. data/lib/sequel/adapters/shared/access.rb +76 -47
  38. data/lib/sequel/adapters/shared/cubrid.rb +16 -11
  39. data/lib/sequel/adapters/shared/db2.rb +46 -19
  40. data/lib/sequel/adapters/shared/firebird.rb +20 -8
  41. data/lib/sequel/adapters/shared/informix.rb +6 -3
  42. data/lib/sequel/adapters/shared/mssql.rb +132 -72
  43. data/lib/sequel/adapters/shared/mysql.rb +112 -65
  44. data/lib/sequel/adapters/shared/oracle.rb +36 -21
  45. data/lib/sequel/adapters/shared/postgres.rb +91 -56
  46. data/lib/sequel/adapters/shared/sqlanywhere.rb +65 -37
  47. data/lib/sequel/adapters/shared/sqlite.rb +67 -32
  48. data/lib/sequel/adapters/sqlanywhere.rb +9 -1
  49. data/lib/sequel/adapters/sqlite.rb +8 -1
  50. data/lib/sequel/adapters/swift.rb +5 -0
  51. data/lib/sequel/adapters/swift/mysql.rb +4 -2
  52. data/lib/sequel/adapters/swift/sqlite.rb +1 -1
  53. data/lib/sequel/adapters/tinytds.rb +10 -3
  54. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +1 -1
  55. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +1 -1
  56. data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -0
  57. data/lib/sequel/adapters/utils/pg_types.rb +14 -6
  58. data/lib/sequel/adapters/utils/replace.rb +4 -2
  59. data/lib/sequel/connection_pool/single.rb +2 -2
  60. data/lib/sequel/core.rb +24 -11
  61. data/lib/sequel/database/connecting.rb +9 -3
  62. data/lib/sequel/database/dataset_defaults.rb +7 -1
  63. data/lib/sequel/database/logging.rb +1 -0
  64. data/lib/sequel/database/misc.rb +5 -2
  65. data/lib/sequel/database/query.rb +7 -5
  66. data/lib/sequel/database/schema_generator.rb +1 -0
  67. data/lib/sequel/database/schema_methods.rb +50 -27
  68. data/lib/sequel/database/transactions.rb +19 -9
  69. data/lib/sequel/dataset/actions.rb +15 -6
  70. data/lib/sequel/dataset/graph.rb +15 -5
  71. data/lib/sequel/dataset/misc.rb +12 -4
  72. data/lib/sequel/dataset/mutation.rb +17 -8
  73. data/lib/sequel/dataset/prepared_statements.rb +3 -2
  74. data/lib/sequel/dataset/query.rb +84 -38
  75. data/lib/sequel/dataset/sql.rb +302 -191
  76. data/lib/sequel/deprecated.rb +26 -17
  77. data/lib/sequel/extensions/_deprecated_identifier_mangling.rb +2 -2
  78. data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
  79. data/lib/sequel/extensions/from_block.rb +1 -0
  80. data/lib/sequel/extensions/graph_each.rb +1 -1
  81. data/lib/sequel/extensions/identifier_mangling.rb +2 -2
  82. data/lib/sequel/extensions/migration.rb +28 -4
  83. data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -0
  84. data/lib/sequel/extensions/schema_dumper.rb +4 -4
  85. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +5 -3
  86. data/lib/sequel/extensions/set_overrides.rb +2 -0
  87. data/lib/sequel/extensions/split_array_nil.rb +2 -2
  88. data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
  89. data/lib/sequel/model.rb +11 -7
  90. data/lib/sequel/model/associations.rb +5 -7
  91. data/lib/sequel/model/base.rb +47 -45
  92. data/lib/sequel/model/dataset_module.rb +9 -14
  93. data/lib/sequel/model/plugins.rb +3 -0
  94. data/lib/sequel/no_core_ext.rb +1 -0
  95. data/lib/sequel/plugins/blacklist_security.rb +1 -1
  96. data/lib/sequel/plugins/boolean_subsets.rb +7 -5
  97. data/lib/sequel/plugins/class_table_inheritance.rb +47 -10
  98. data/lib/sequel/plugins/dataset_associations.rb +1 -1
  99. data/lib/sequel/plugins/def_dataset_method.rb +90 -0
  100. data/lib/sequel/plugins/finder.rb +240 -0
  101. data/lib/sequel/plugins/inverted_subsets.rb +19 -12
  102. data/lib/sequel/plugins/many_through_many.rb +1 -1
  103. data/lib/sequel/plugins/nested_attributes.rb +1 -1
  104. data/lib/sequel/plugins/schema.rb +1 -1
  105. data/lib/sequel/plugins/single_table_inheritance.rb +7 -1
  106. data/lib/sequel/plugins/subset_conditions.rb +11 -3
  107. data/lib/sequel/plugins/whitelist_security.rb +118 -0
  108. data/lib/sequel/sql.rb +80 -36
  109. data/lib/sequel/timezones.rb +2 -0
  110. data/lib/sequel/version.rb +1 -1
  111. data/spec/adapters/mssql_spec.rb +20 -0
  112. data/spec/adapters/mysql_spec.rb +1 -1
  113. data/spec/adapters/oracle_spec.rb +12 -8
  114. data/spec/adapters/postgres_spec.rb +1 -1
  115. data/spec/adapters/spec_helper.rb +1 -1
  116. data/spec/adapters/sqlite_spec.rb +36 -34
  117. data/spec/core/connection_pool_spec.rb +2 -1
  118. data/spec/core/database_spec.rb +87 -9
  119. data/spec/core/dataset_spec.rb +501 -129
  120. data/spec/core/deprecated_spec.rb +1 -1
  121. data/spec/core/expression_filters_spec.rb +146 -60
  122. data/spec/core/mock_adapter_spec.rb +1 -1
  123. data/spec/core/object_graph_spec.rb +61 -9
  124. data/spec/core/placeholder_literalizer_spec.rb +20 -2
  125. data/spec/core/schema_generator_spec.rb +6 -6
  126. data/spec/core/schema_spec.rb +54 -5
  127. data/spec/core_extensions_spec.rb +122 -18
  128. data/spec/deprecation_helper.rb +27 -2
  129. data/spec/extensions/_deprecated_identifier_mangling_spec.rb +6 -6
  130. data/spec/extensions/association_proxies_spec.rb +2 -2
  131. data/spec/extensions/auto_literal_strings_spec.rb +212 -0
  132. data/spec/extensions/blacklist_security_spec.rb +1 -0
  133. data/spec/extensions/class_table_inheritance_spec.rb +1037 -39
  134. data/spec/extensions/column_select_spec.rb +20 -8
  135. data/spec/extensions/columns_introspection_spec.rb +3 -3
  136. data/spec/extensions/core_refinements_spec.rb +29 -12
  137. data/spec/extensions/dataset_associations_spec.rb +12 -12
  138. data/spec/extensions/def_dataset_method_spec.rb +100 -0
  139. data/spec/extensions/error_sql_spec.rb +1 -1
  140. data/spec/extensions/finder_spec.rb +260 -0
  141. data/spec/extensions/graph_each_spec.rb +2 -2
  142. data/spec/extensions/identifier_mangling_spec.rb +14 -8
  143. data/spec/extensions/inverted_subsets_spec.rb +4 -4
  144. data/spec/extensions/lazy_attributes_spec.rb +7 -0
  145. data/spec/extensions/many_through_many_spec.rb +38 -14
  146. data/spec/extensions/nested_attributes_spec.rb +18 -6
  147. data/spec/extensions/no_auto_literal_strings_spec.rb +1 -1
  148. data/spec/extensions/pg_enum_spec.rb +16 -1
  149. data/spec/extensions/pg_interval_spec.rb +11 -2
  150. data/spec/extensions/pg_loose_count_spec.rb +5 -0
  151. data/spec/extensions/pg_row_spec.rb +25 -0
  152. data/spec/extensions/prepared_statements_spec.rb +10 -1
  153. data/spec/extensions/query_spec.rb +2 -2
  154. data/spec/extensions/schema_dumper_spec.rb +2 -2
  155. data/spec/extensions/schema_spec.rb +2 -2
  156. data/spec/extensions/set_overrides_spec.rb +7 -3
  157. data/spec/extensions/sql_expr_spec.rb +0 -1
  158. data/spec/extensions/subset_conditions_spec.rb +6 -6
  159. data/spec/extensions/table_select_spec.rb +24 -12
  160. data/spec/extensions/to_dot_spec.rb +4 -4
  161. data/spec/extensions/whitelist_security_spec.rb +131 -0
  162. data/spec/integration/dataset_test.rb +9 -5
  163. data/spec/integration/model_test.rb +2 -0
  164. data/spec/integration/plugin_test.rb +2 -2
  165. data/spec/integration/spec_helper.rb +1 -1
  166. data/spec/model/associations_spec.rb +39 -11
  167. data/spec/model/base_spec.rb +44 -24
  168. data/spec/model/class_dataset_methods_spec.rb +18 -16
  169. data/spec/model/dataset_methods_spec.rb +4 -4
  170. data/spec/model/eager_loading_spec.rb +84 -24
  171. data/spec/model/model_spec.rb +97 -63
  172. data/spec/model/record_spec.rb +21 -13
  173. metadata +13 -2
@@ -13,20 +13,29 @@ describe "prepared_statements plugin" do
13
13
  @db.sqls
14
14
  end
15
15
 
16
- it "should correctly lookup by primary key for joined dataset" do
16
+ deprecated "should correctly lookup by primary key for joined dataset" do
17
17
  @c.dataset = @c.dataset.from(:people, :people2)
18
18
  @db.sqls
19
19
  @c[1].must_equal @p
20
20
  @db.sqls.must_equal ["SELECT * FROM people, people2 WHERE (people.id = 1) LIMIT 1 -- read_only"]
21
21
  end
22
22
 
23
+ it "should correctly lookup by primary key for dataset using subquery" do
24
+ @c.dataset = @c.dataset.from(:people, :people2).from_self(:alias=>:people)
25
+ @db.sqls
26
+ @c[1].must_equal @p
27
+ @db.sqls.must_equal ["SELECT * FROM (SELECT * FROM people, people2) AS people WHERE (id = 1) LIMIT 1 -- read_only"]
28
+ end
29
+
23
30
  it "should use prepared statements for pk lookups only if default is not optimized" do
24
31
  @c.send(:use_prepared_statements_for_pk_lookup?).must_equal false
25
32
  @c.set_primary_key [:id, :name]
26
33
  @c.send(:use_prepared_statements_for_pk_lookup?).must_equal true
27
34
  @c.set_primary_key :id
35
+ deprecated do
28
36
  @c.dataset = @c.dataset.from(:people, :people2)
29
37
  @c.send(:use_prepared_statements_for_pk_lookup?).must_equal false
38
+ end
30
39
  @c.dataset = @db[:people].select(:id, :name, :i)
31
40
  @c.send(:use_prepared_statements_for_pk_lookup?).must_equal true
32
41
  end
@@ -31,7 +31,7 @@ describe "Dataset#query" do
31
31
 
32
32
  it "should support #select" do
33
33
  q = @d.query do
34
- select :a, :b___mongo
34
+ select :a, Sequel[:b].as(:mongo)
35
35
  from :yyy
36
36
  end
37
37
  q.class.must_equal @d.class
@@ -91,7 +91,7 @@ describe "Dataset#query" do
91
91
  unless Sequel.mock.dataset.frozen?
92
92
  deprecated "should have an appropriate mutation method" do
93
93
  @d.query! do
94
- select :a, :b___mongo
94
+ select :a, Sequel[:b].as(:mongo)
95
95
  from :yyy
96
96
  end
97
97
  @d.sql.must_equal "SELECT a, b AS mongo FROM yyy"
@@ -1,9 +1,9 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
2
2
 
3
- describe "Sequel::Schema::Generator dump methods" do
3
+ describe "Sequel::Schema::CreateTableGenerator dump methods" do
4
4
  before do
5
5
  @d = Sequel::Database.new.extension(:schema_dumper)
6
- @g = Sequel::Schema::Generator
6
+ @g = Sequel::Schema::CreateTableGenerator
7
7
  end
8
8
 
9
9
  it "should allow the same table information to be converted to a string for evaling inside of another instance with the same result" do
@@ -60,12 +60,12 @@ describe Sequel::Model, "create_table and schema" do
60
60
  end
61
61
 
62
62
  it "should return the schema generator via schema" do
63
- @model.schema.must_be_kind_of(Sequel::Schema::Generator)
63
+ @model.schema.must_be_kind_of(Sequel::Schema::CreateTableGenerator)
64
64
  end
65
65
 
66
66
  it "should use the superclasses schema if it exists" do
67
67
  @submodel = Class.new(@model)
68
- @submodel.schema.must_be_kind_of(Sequel::Schema::Generator)
68
+ @submodel.schema.must_be_kind_of(Sequel::Schema::CreateTableGenerator)
69
69
  end
70
70
 
71
71
  it "should return nil if no schema is present" do
@@ -2,7 +2,9 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
2
 
3
3
  describe "Sequel::Dataset #set_defaults" do
4
4
  before do
5
- @ds = Sequel.mock.dataset.from(:items).extension(:set_overrides).set_defaults(:x=>1)
5
+ deprecated do
6
+ @ds = Sequel.mock.dataset.from(:items).extension(:set_overrides).set_defaults(:x=>1)
7
+ end
6
8
  end
7
9
 
8
10
  it "should set the default values for inserts" do
@@ -21,7 +23,7 @@ describe "Sequel::Dataset #set_defaults" do
21
23
  @ds.set_defaults(:x=>2).update_sql.must_equal "UPDATE items SET x = 2"
22
24
  end
23
25
 
24
- it "should not affect String update arguments" do
26
+ deprecated "should not affect String update arguments" do
25
27
  @ds.update_sql('y = 2').must_equal "UPDATE items SET y = 2"
26
28
  end
27
29
 
@@ -37,7 +39,9 @@ end
37
39
 
38
40
  describe "Sequel::Dataset #set_overrides" do
39
41
  before do
40
- @ds = Sequel.mock.dataset.from(:items).extension(:set_overrides).set_overrides(:x=>1)
42
+ deprecated do
43
+ @ds = Sequel.mock.dataset.from(:items).extension(:set_overrides).set_overrides(:x=>1)
44
+ end
41
45
  end
42
46
 
43
47
  it "should override the given values for inserts" do
@@ -44,7 +44,6 @@ describe "Sequel sql_expr extension" do
44
44
 
45
45
  it "Proc#sql_expr should should treat the object as a virtual row block" do
46
46
  @ds.literal(proc{a}.sql_expr).must_equal "a"
47
- @ds.literal(proc{a__b}.sql_expr).must_equal "a.b"
48
47
  @ds.literal(proc{a(b)}.sql_expr).must_equal "a(b)"
49
48
  end
50
49
 
@@ -7,13 +7,13 @@ describe "subset_conditions plugin" do
7
7
  end
8
8
 
9
9
  it "should provide *_conditions method return the arguments passed" do
10
- @c.subset(:published, :published => true)
10
+ @c.dataset_module{subset(:published, :published => true)}
11
11
  @c.where(@c.published_conditions).sql.must_equal @c.published.sql
12
12
 
13
- @c.subset(:active, :active)
13
+ @c.dataset_module{where(:active, :active)}
14
14
  @c.where(@c.active_conditions).sql.must_equal @c.active.sql
15
15
 
16
- @c.subset(:active_published, Sequel.&(:active, :published => true))
16
+ @c.dataset_module{subset(:active_published, Sequel.&(:active, :published => true))}
17
17
  @c.where(@c.active_published_conditions).sql.must_equal @c.active_published.sql
18
18
  @c.where(Sequel.&(@c.active_conditions, @c.published_conditions)).sql.must_equal @c.active_published.sql
19
19
  @c.where(Sequel.|(@c.active_conditions, @c.published_conditions)).sql.must_equal "SELECT * FROM a WHERE (active OR (published IS TRUE))"
@@ -22,14 +22,14 @@ describe "subset_conditions plugin" do
22
22
 
23
23
  it "should work with blocks" do
24
24
  p1 = proc{{:published=>true}}
25
- @c.subset(:published, &p1)
25
+ @c.dataset_module{subset(:published, &p1)}
26
26
  @c.where(@c.published_conditions).sql.must_equal @c.published.sql
27
27
 
28
28
  p2 = :active
29
- @c.subset(:active, p2)
29
+ @c.dataset_module{subset(:active, p2)}
30
30
  @c.where(@c.active_conditions).sql.must_equal @c.active.sql
31
31
 
32
- @c.subset(:active_published, p2, &p1)
32
+ @c.dataset_module{subset(:active_published, p2, &p1)}
33
33
  @c.where(@c.active_published_conditions).sql.must_equal @c.active_published.sql
34
34
  @c.where(Sequel.&(@c.active_conditions, @c.published_conditions)).sql.must_equal @c.active_published.sql
35
35
  @c.where(Sequel.|(@c.active_conditions, @c.published_conditions)).sql.must_equal "SELECT * FROM a WHERE (active OR (published IS TRUE))"
@@ -17,25 +17,16 @@ describe "Sequel::Plugins::TableSelect" do
17
17
  end
18
18
 
19
19
  it "should handle qualified tables" do
20
- @Album.dataset = :s__albums
21
- @Album.plugin :table_select
22
- @Album.dataset.sql.must_equal 'SELECT s.albums.* FROM s.albums'
23
-
24
20
  @Album.dataset = Sequel.qualify(:s2, :albums)
21
+ @Album.plugin :table_select
25
22
  @Album.dataset.sql.must_equal 'SELECT s2.albums.* FROM s2.albums'
26
23
  end
27
24
 
28
25
  it "should handle aliases" do
29
- @Album.dataset = :albums___a
30
- @Album.plugin :table_select
31
- @Album.dataset.sql.must_equal 'SELECT a.* FROM albums AS a'
32
-
33
26
  @Album.dataset = Sequel.as(:albums, :b)
27
+ @Album.plugin :table_select
34
28
  @Album.dataset.sql.must_equal 'SELECT b.* FROM albums AS b'
35
29
 
36
- @Album.dataset = :s__albums___a
37
- @Album.dataset.sql.must_equal 'SELECT a.* FROM s.albums AS a'
38
-
39
30
  @Album.dataset = @Album.db[:albums].from_self
40
31
  @Album.dataset.sql.must_equal 'SELECT t1.* FROM (SELECT * FROM albums) AS t1'
41
32
 
@@ -43,6 +34,18 @@ describe "Sequel::Plugins::TableSelect" do
43
34
  @Album.dataset.sql.must_equal 'SELECT b.* FROM (SELECT * FROM albums) AS b'
44
35
  end
45
36
 
37
+ with_symbol_splitting "should handle splittable symbols" do
38
+ @Album.dataset = :albums___a
39
+ @Album.plugin :table_select
40
+ @Album.dataset.sql.must_equal 'SELECT a.* FROM albums AS a'
41
+
42
+ @Album.dataset = :s__albums___a
43
+ @Album.dataset.sql.must_equal 'SELECT a.* FROM s.albums AS a'
44
+
45
+ @Album.dataset = :s__albums
46
+ @Album.dataset.sql.must_equal 'SELECT s.albums.* FROM s.albums'
47
+ end
48
+
46
49
  it "should not add a table.* selection on existing dataset with explicit selection" do
47
50
  @Album.dataset = @Album.dataset.select(:name)
48
51
  @Album.plugin :table_select
@@ -52,7 +55,16 @@ describe "Sequel::Plugins::TableSelect" do
52
55
  @Album.dataset.sql.must_equal 'SELECT name, artist FROM albums'
53
56
  end
54
57
 
55
- it "should not add a table.* selection on existing dataset with multiple tables" do
58
+ it "should add a table.* selection on existing dataset with subquery" do
59
+ @Album.dataset = @Album.db.from(:a1, :a2).from_self(:alias=>:foo)
60
+ @Album.plugin :table_select
61
+ @Album.dataset.sql.must_equal 'SELECT foo.* FROM (SELECT * FROM a1, a2) AS foo'
62
+
63
+ @Album.dataset = @Album.db.from(:a1).cross_join(:a2).from_self(:alias=>:foo)
64
+ @Album.dataset.sql.must_equal 'SELECT foo.* FROM (SELECT * FROM a1 CROSS JOIN a2) AS foo'
65
+ end
66
+
67
+ deprecated "should not add a table.* selection on existing dataset with multiple tables" do
56
68
  @Album.dataset = @Album.db.from(:a1, :a2)
57
69
  @Album.plugin :table_select
58
70
  @Album.dataset.sql.must_equal 'SELECT * FROM a1, a2'
@@ -80,7 +80,7 @@ END
80
80
  end
81
81
 
82
82
  it "should handle LiteralStrings" do
83
- dot(@ds.filter('a')).must_equal ["1 -> 2 [label=\"where\"];", "2 [label=\"Sequel.lit(\\\"(a)\\\")\"];"]
83
+ dot(@ds.filter(Sequel.lit('a'))).must_equal ["1 -> 2 [label=\"where\"];", "2 [label=\"Sequel.lit(\\\"(a)\\\")\"];"]
84
84
  end
85
85
 
86
86
  it "should handle true, false, nil" do
@@ -96,7 +96,7 @@ END
96
96
  end
97
97
 
98
98
  it "should handle SQL::QualifiedIdentifiers" do
99
- dot(@ds.select{a__b}).must_equal ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"QualifiedIdentifier\"];", "3 -> 4 [label=\"table\"];", "4 [label=\"\\\"a\\\"\"];", "3 -> 5 [label=\"column\"];", "5 [label=\"\\\"b\\\"\"];"]
99
+ dot(@ds.select{a[b]}).must_equal ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"QualifiedIdentifier\"];", "3 -> 4 [label=\"table\"];", "4 [label=\"\\\"a\\\"\"];", "3 -> 5 [label=\"column\"];", "5 [label=\"\\\"b\\\"\"];"]
100
100
  end
101
101
 
102
102
  it "should handle SQL::OrderedExpressions" do
@@ -128,11 +128,11 @@ END
128
128
  end
129
129
 
130
130
  it "should handle SQL::Function with a window" do
131
- dot(@ds.select{sum{}.over(:partition=>:a)}).must_equal ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"Function: sum\"];", "3 -> 4 [label=\"args\"];", "4 [label=\"Array\"];", "3 -> 5 [label=\"opts\"];", "5 [label=\"Hash\"];", "5 -> 6 [label=\"over\"];", "6 [label=\"Window\"];", "6 -> 7 [label=\"opts\"];", "7 [label=\"Hash\"];", "7 -> 8 [label=\"partition\"];", "8 [label=\":a\"];"]
131
+ dot(@ds.select(Sequel.function(:sum).over(:partition=>:a))).must_equal ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"Function: sum\"];", "3 -> 4 [label=\"args\"];", "4 [label=\"Array\"];", "3 -> 5 [label=\"opts\"];", "5 [label=\"Hash\"];", "5 -> 6 [label=\"over\"];", "6 [label=\"Window\"];", "6 -> 7 [label=\"opts\"];", "7 [label=\"Hash\"];", "7 -> 8 [label=\"partition\"];", "8 [label=\":a\"];"]
132
132
  end
133
133
 
134
134
  it "should handle SQL::PlaceholderLiteralString" do
135
- dot(@ds.where("?", true)).must_equal ["1 -> 2 [label=\"where\"];", "2 [label=\"PlaceholderLiteralString: \\\"(?)\\\"\"];", "2 -> 3 [label=\"args\"];", "3 [label=\"Array\"];", "3 -> 4 [label=\"0\"];", "4 [label=\"true\"];"]
135
+ dot(@ds.where(Sequel.lit("?", true))).must_equal ["1 -> 2 [label=\"where\"];", "2 [label=\"PlaceholderLiteralString: \\\"(?)\\\"\"];", "2 -> 3 [label=\"args\"];", "3 [label=\"Array\"];", "3 -> 4 [label=\"0\"];", "4 [label=\"true\"];"]
136
136
  end
137
137
 
138
138
  it "should handle JOIN ON" do
@@ -0,0 +1,131 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe Sequel::Model, "#(set|update)_(all|only)" do
4
+ before do
5
+ @c = Class.new(Sequel::Model(:items)) do
6
+ set_primary_key :id
7
+ columns :x, :y, :z, :id
8
+ end
9
+ @c.plugin :whitelist_security
10
+ @c.set_allowed_columns :x
11
+ @c.strict_param_setting = false
12
+ @o1 = @c.new
13
+ DB.reset
14
+ end
15
+
16
+ it "should raise errors if not all hash fields can be set and strict_param_setting is true" do
17
+ @c.strict_param_setting = true
18
+
19
+ proc{@c.new.set_all(:x => 1, :y => 2, :z=>3, :use_after_commit_rollback => false)}.must_raise(Sequel::MassAssignmentRestriction)
20
+ (o = @c.new).set_all(:x => 1, :y => 2, :z=>3)
21
+ o.values.must_equal(:x => 1, :y => 2, :z=>3)
22
+
23
+ proc{@c.new.set_only({:x => 1, :y => 2, :z=>3, :id=>4}, :x, :y)}.must_raise(Sequel::MassAssignmentRestriction)
24
+ proc{@c.new.set_only({:x => 1, :y => 2, :z=>3}, :x, :y)}.must_raise(Sequel::MassAssignmentRestriction)
25
+ (o = @c.new).set_only({:x => 1, :y => 2}, :x, :y)
26
+ o.values.must_equal(:x => 1, :y => 2)
27
+ end
28
+
29
+ it "#set_all should set all attributes including the primary key" do
30
+ @o1.set_all(:x => 1, :y => 2, :z=>3, :id=>4)
31
+ @o1.values.must_equal(:id =>4, :x => 1, :y => 2, :z=>3)
32
+ end
33
+
34
+ it "#set_all should set not set restricted fields" do
35
+ @o1.use_after_commit_rollback.must_be_nil
36
+ @o1.set_all(:x => 1, :use_after_commit_rollback => true)
37
+ @o1.use_after_commit_rollback.must_be_nil
38
+ @o1.values.must_equal(:x => 1)
39
+ end
40
+
41
+ it "#set_only should only set given attributes" do
42
+ @o1.set_only({:x => 1, :y => 2, :z=>3, :id=>4}, [:x, :y])
43
+ @o1.values.must_equal(:x => 1, :y => 2)
44
+ @o1.set_only({:x => 4, :y => 5, :z=>6, :id=>7}, :x, :y)
45
+ @o1.values.must_equal(:x => 4, :y => 5)
46
+ @o1.set_only({:x => 9, :y => 8, :z=>6, :id=>7}, :x, :y, :id)
47
+ @o1.values.must_equal(:x => 9, :y => 8, :id=>7)
48
+ end
49
+
50
+ it "#update_all should update all attributes" do
51
+ @c.new.update_all(:x => 1)
52
+ DB.sqls.must_equal ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE id = 10"]
53
+ @c.new.update_all(:y => 1)
54
+ DB.sqls.must_equal ["INSERT INTO items (y) VALUES (1)", "SELECT * FROM items WHERE id = 10"]
55
+ @c.new.update_all(:z => 1)
56
+ DB.sqls.must_equal ["INSERT INTO items (z) VALUES (1)", "SELECT * FROM items WHERE id = 10"]
57
+ end
58
+
59
+ it "#update_only should only update given attributes" do
60
+ @o1.update_only({:x => 1, :y => 2, :z=>3, :id=>4}, [:x])
61
+ DB.sqls.must_equal ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE id = 10"]
62
+ @c.new.update_only({:x => 1, :y => 2, :z=>3, :id=>4}, :x)
63
+ DB.sqls.must_equal ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE id = 10"]
64
+ end
65
+ end
66
+
67
+ describe Sequel::Model, ".strict_param_setting" do
68
+ before do
69
+ @c = Class.new(Sequel::Model(:blahblah)) do
70
+ columns :x, :y, :z, :id
71
+ end
72
+ @c.plugin :whitelist_security
73
+ @c.set_allowed_columns :x, :y
74
+ end
75
+
76
+ it "should raise an error if a missing/restricted column/method is accessed" do
77
+ proc{@c.new(:z=>1)}.must_raise(Sequel::MassAssignmentRestriction)
78
+ proc{@c.create(:z=>1)}.must_raise(Sequel::MassAssignmentRestriction)
79
+ c = @c.new
80
+ proc{c.set(:z=>1)}.must_raise(Sequel::MassAssignmentRestriction)
81
+ proc{c.update(:z=>1)}.must_raise(Sequel::MassAssignmentRestriction)
82
+ proc{c.set_all(:use_after_commit_rollback => false)}.must_raise(Sequel::MassAssignmentRestriction)
83
+ proc{c.set_only({:x=>1}, :y)}.must_raise(Sequel::MassAssignmentRestriction)
84
+ proc{c.update_all(:use_after_commit_rollback=>false)}.must_raise(Sequel::MassAssignmentRestriction)
85
+ proc{c.update_only({:x=>1}, :y)}.must_raise(Sequel::MassAssignmentRestriction)
86
+ end
87
+ end
88
+
89
+ describe Sequel::Model, ".allowed_columns " do
90
+ before do
91
+ @c = Class.new(Sequel::Model(:blahblah)) do
92
+ columns :x, :y, :z
93
+ end
94
+ @c.plugin :whitelist_security
95
+ @c.strict_param_setting = false
96
+ @c.instance_variable_set(:@columns, [:x, :y, :z])
97
+ DB.reset
98
+ end
99
+
100
+ it "should set the allowed columns correctly" do
101
+ @c.allowed_columns.must_be_nil
102
+ @c.set_allowed_columns :x
103
+ @c.allowed_columns.must_equal [:x]
104
+ @c.set_allowed_columns :x, :y
105
+ @c.allowed_columns.must_equal [:x, :y]
106
+ end
107
+
108
+ it "should only set allowed columns by default" do
109
+ @c.set_allowed_columns :x, :y
110
+ i = @c.new(:x => 1, :y => 2, :z => 3)
111
+ i.values.must_equal(:x => 1, :y => 2)
112
+ i.set(:x => 4, :y => 5, :z => 6)
113
+ i.values.must_equal(:x => 4, :y => 5)
114
+
115
+ @c.dataset = @c.dataset.with_fetch(:x => 7)
116
+ i = @c.new
117
+ i.update(:x => 7, :z => 9)
118
+ i.values.must_equal(:x => 7)
119
+ DB.sqls.must_equal ["INSERT INTO blahblah (x) VALUES (7)", "SELECT * FROM blahblah WHERE id = 10"]
120
+ end
121
+ end
122
+
123
+ describe "Sequel::Model.freeze" do
124
+ it "should freeze the model class and not allow any changes" do
125
+ model = Class.new(Sequel::Model(:items))
126
+ model.plugin :whitelist_security
127
+ model.set_allowed_columns [:id]
128
+ model.freeze
129
+ model.allowed_columns.frozen?.must_equal true
130
+ end
131
+ end
@@ -866,9 +866,9 @@ if DB.dataset.supports_window_functions?
866
866
  end
867
867
 
868
868
  it "should give correct results for ranking window functions with orders" do
869
- @ds.select(:id){rank{}.over(:partition=>:group_id, :order=>:id).as(:rank)}.all.
869
+ @ds.select(:id){rank.function.over(:partition=>:group_id, :order=>:id).as(:rank)}.all.
870
870
  must_equal [{:rank=>1, :id=>1}, {:rank=>2, :id=>2}, {:rank=>3, :id=>3}, {:rank=>1, :id=>4}, {:rank=>2, :id=>5}, {:rank=>3, :id=>6}]
871
- @ds.select(:id){rank{}.over(:order=>id).as(:rank)}.all.
871
+ @ds.select(:id){rank.function.over(:order=>id).as(:rank)}.all.
872
872
  must_equal [{:rank=>1, :id=>1}, {:rank=>2, :id=>2}, {:rank=>3, :id=>3}, {:rank=>4, :id=>4}, {:rank=>5, :id=>5}, {:rank=>6, :id=>6}]
873
873
  end
874
874
 
@@ -1568,8 +1568,10 @@ describe "Dataset string methods" do
1568
1568
  @db = DB
1569
1569
  csc = {}
1570
1570
  cic = {}
1571
- csc[:collate] = @db.dataset_class::CASE_SENSITIVE_COLLATION if defined? @db.dataset_class::CASE_SENSITIVE_COLLATION
1572
- cic[:collate] = @db.dataset_class::CASE_INSENSITIVE_COLLATION if defined? @db.dataset_class::CASE_INSENSITIVE_COLLATION
1571
+ if @db.database_type == :mssql
1572
+ csc[:collate] = 'Latin1_General_CS_AS'
1573
+ cic[:collate] = 'Latin1_General_CI_AS'
1574
+ end
1573
1575
  @db.create_table!(:a) do
1574
1576
  String :a, csc
1575
1577
  String :b, cic
@@ -1752,7 +1754,9 @@ describe "Dataset defaults and overrides" do
1752
1754
  before(:all) do
1753
1755
  @db = DB
1754
1756
  @db.create_table!(:a){Integer :a}
1755
- @ds = @db[:a].order(:a).extension(:set_overrides)
1757
+ deprecated do
1758
+ @ds = @db[:a].order(:a).extension(:set_overrides)
1759
+ end
1756
1760
  end
1757
1761
  before do
1758
1762
  @ds.delete
@@ -24,6 +24,7 @@ describe "Sequel::Model basic support" do
24
24
 
25
25
  it ".finder should create method that returns first matching item" do
26
26
  def Item.by_name(name) where(:name=>name) end
27
+ Item.plugin :finder
27
28
  Item.finder :by_name
28
29
  Item.first_by_name('J').must_be_nil
29
30
  Item.create(:name=>'J')
@@ -33,6 +34,7 @@ describe "Sequel::Model basic support" do
33
34
 
34
35
  it ".prepared_finder should create method that returns first matching item" do
35
36
  def Item.by_name(name) where(:name=>name) end
37
+ Item.plugin :finder
36
38
  Item.prepared_finder :by_name
37
39
  Item.first_by_name('J').must_be_nil
38
40
  Item.create(:name=>'J')
@@ -26,7 +26,7 @@ describe "Class Table Inheritance Plugin" do
26
26
  before do
27
27
  [:staff, :executives, :managers, :employees].each{|t| @db[t].delete}
28
28
  class ::Employee < Sequel::Model(@db)
29
- plugin :class_table_inheritance, :key=>:kind, :table_map=>{:Staff=>:staff}
29
+ plugin :class_table_inheritance, :key=>:kind, :table_map=>{:Staff=>:staff}, :alias=>:employees
30
30
  end
31
31
  class ::Manager < Employee
32
32
  one_to_many :staff_members, :class=>:Staff
@@ -166,7 +166,7 @@ describe "Class Table Inheritance Plugin" do
166
166
  end
167
167
 
168
168
  it "should handle eagerly graphing one_to_many relationships" do
169
- es = Executive.where(:name=>'Ex').eager_graph(:staff_members).all
169
+ es = Executive.where(Sequel[:employees][:name]=>'Ex').eager_graph(:staff_members).all
170
170
  es.must_equal [Executive[@i4]]
171
171
  es.map{|x| x.staff_members}.must_equal [[Staff[@i2]]]
172
172
  end