sequel 4.12.0 → 4.13.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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +64 -0
  3. data/Rakefile +3 -1
  4. data/bin/sequel +13 -5
  5. data/doc/release_notes/4.13.0.txt +169 -0
  6. data/doc/sql.rdoc +3 -3
  7. data/lib/sequel/adapters/do.rb +11 -23
  8. data/lib/sequel/adapters/do/mysql.rb +8 -0
  9. data/lib/sequel/adapters/do/postgres.rb +8 -0
  10. data/lib/sequel/adapters/do/{sqlite.rb → sqlite3.rb} +9 -0
  11. data/lib/sequel/adapters/jdbc.rb +16 -139
  12. data/lib/sequel/adapters/jdbc/as400.rb +9 -0
  13. data/lib/sequel/adapters/jdbc/cubrid.rb +9 -0
  14. data/lib/sequel/adapters/jdbc/db2.rb +9 -0
  15. data/lib/sequel/adapters/jdbc/derby.rb +9 -0
  16. data/lib/sequel/adapters/jdbc/{firebird.rb → firebirdsql.rb} +9 -0
  17. data/lib/sequel/adapters/jdbc/h2.rb +10 -0
  18. data/lib/sequel/adapters/jdbc/hsqldb.rb +9 -0
  19. data/lib/sequel/adapters/jdbc/{informix.rb → informix-sqli.rb} +9 -0
  20. data/lib/sequel/adapters/jdbc/{progress.rb → jdbcprogress.rb} +9 -0
  21. data/lib/sequel/adapters/jdbc/jtds.rb +10 -0
  22. data/lib/sequel/adapters/jdbc/mysql.rb +14 -0
  23. data/lib/sequel/adapters/jdbc/oracle.rb +9 -0
  24. data/lib/sequel/adapters/jdbc/postgresql.rb +9 -0
  25. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +23 -0
  26. data/lib/sequel/adapters/jdbc/sqlite.rb +10 -0
  27. data/lib/sequel/adapters/jdbc/sqlserver.rb +10 -0
  28. data/lib/sequel/adapters/odbc.rb +6 -14
  29. data/lib/sequel/adapters/odbc/db2.rb +9 -0
  30. data/lib/sequel/adapters/odbc/mssql.rb +8 -0
  31. data/lib/sequel/adapters/odbc/progress.rb +8 -0
  32. data/lib/sequel/adapters/oracle.rb +1 -1
  33. data/lib/sequel/adapters/postgres.rb +1 -1
  34. data/lib/sequel/adapters/shared/firebird.rb +8 -1
  35. data/lib/sequel/adapters/shared/mssql.rb +68 -27
  36. data/lib/sequel/adapters/shared/mysql.rb +3 -5
  37. data/lib/sequel/adapters/shared/oracle.rb +17 -3
  38. data/lib/sequel/adapters/shared/postgres.rb +9 -4
  39. data/lib/sequel/adapters/shared/sqlanywhere.rb +6 -6
  40. data/lib/sequel/database/connecting.rb +38 -17
  41. data/lib/sequel/dataset/actions.rb +6 -2
  42. data/lib/sequel/dataset/graph.rb +18 -20
  43. data/lib/sequel/dataset/misc.rb +37 -0
  44. data/lib/sequel/dataset/prepared_statements.rb +1 -2
  45. data/lib/sequel/dataset/query.rb +1 -0
  46. data/lib/sequel/dataset/sql.rb +17 -10
  47. data/lib/sequel/extensions/dataset_source_alias.rb +90 -0
  48. data/lib/sequel/extensions/pg_array.rb +14 -10
  49. data/lib/sequel/extensions/pg_enum.rb +135 -0
  50. data/lib/sequel/extensions/pg_hstore.rb +4 -6
  51. data/lib/sequel/extensions/pg_inet.rb +4 -5
  52. data/lib/sequel/extensions/pg_interval.rb +3 -3
  53. data/lib/sequel/extensions/pg_json.rb +16 -12
  54. data/lib/sequel/extensions/pg_range.rb +5 -3
  55. data/lib/sequel/extensions/pg_row.rb +2 -2
  56. data/lib/sequel/extensions/round_timestamps.rb +52 -0
  57. data/lib/sequel/model.rb +5 -2
  58. data/lib/sequel/model/associations.rb +29 -3
  59. data/lib/sequel/model/base.rb +68 -29
  60. data/lib/sequel/plugins/class_table_inheritance.rb +25 -16
  61. data/lib/sequel/plugins/column_select.rb +57 -0
  62. data/lib/sequel/plugins/composition.rb +14 -16
  63. data/lib/sequel/plugins/dirty.rb +9 -11
  64. data/lib/sequel/plugins/insert_returning_select.rb +70 -0
  65. data/lib/sequel/plugins/instance_filters.rb +7 -9
  66. data/lib/sequel/plugins/lazy_attributes.rb +16 -4
  67. data/lib/sequel/plugins/list.rb +9 -0
  68. data/lib/sequel/plugins/modification_detection.rb +90 -0
  69. data/lib/sequel/plugins/serialization.rb +13 -15
  70. data/lib/sequel/plugins/serialization_modification_detection.rb +9 -9
  71. data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
  72. data/lib/sequel/plugins/timestamps.rb +6 -6
  73. data/lib/sequel/version.rb +1 -1
  74. data/spec/adapters/mysql_spec.rb +7 -0
  75. data/spec/adapters/postgres_spec.rb +41 -0
  76. data/spec/bin_spec.rb +4 -1
  77. data/spec/core/database_spec.rb +6 -0
  78. data/spec/core/dataset_spec.rb +100 -90
  79. data/spec/core/object_graph_spec.rb +5 -0
  80. data/spec/extensions/class_table_inheritance_spec.rb +18 -13
  81. data/spec/extensions/column_select_spec.rb +108 -0
  82. data/spec/extensions/composition_spec.rb +20 -0
  83. data/spec/extensions/dataset_source_alias_spec.rb +51 -0
  84. data/spec/extensions/insert_returning_select_spec.rb +46 -0
  85. data/spec/extensions/lazy_attributes_spec.rb +24 -20
  86. data/spec/extensions/list_spec.rb +5 -0
  87. data/spec/extensions/modification_detection_spec.rb +80 -0
  88. data/spec/extensions/pg_enum_spec.rb +64 -0
  89. data/spec/extensions/pg_json_spec.rb +7 -13
  90. data/spec/extensions/prepared_statements_spec.rb +6 -4
  91. data/spec/extensions/round_timestamps_spec.rb +43 -0
  92. data/spec/extensions/serialization_modification_detection_spec.rb +10 -1
  93. data/spec/extensions/serialization_spec.rb +18 -0
  94. data/spec/extensions/single_table_inheritance_spec.rb +5 -0
  95. data/spec/extensions/timestamps_spec.rb +6 -0
  96. data/spec/integration/plugin_test.rb +14 -8
  97. data/spec/integration/prepared_statement_test.rb +12 -0
  98. data/spec/model/associations_spec.rb +24 -0
  99. data/spec/model/model_spec.rb +13 -3
  100. data/spec/model/record_spec.rb +24 -1
  101. metadata +22 -6
@@ -106,6 +106,11 @@ describe "List plugin" do
106
106
  "SELECT * FROM items WHERE (id = 3) ORDER BY scope_id, position LIMIT 1"]
107
107
  end
108
108
 
109
+ it "should update positions automatically on deletion" do
110
+ @o.destroy
111
+ @db.sqls.should == ["DELETE FROM items WHERE (id = 7)", "UPDATE items SET position = (position - 1) WHERE (position > 3)"]
112
+ end
113
+
109
114
  it "should have last_position return the last position in the list" do
110
115
  @c.dataset._fetch = {:max=>10}
111
116
  @o.last_position.should == 10
@@ -0,0 +1,80 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+ require 'yaml'
3
+
4
+ describe "serialization_modification_detection plugin" do
5
+ before do
6
+ @ds = Sequel.mock(:fetch=>{:id=>1, :a=>'a', :b=>1, :c=>['a'], :d=>{'b'=>'c'}}, :numrows=>1, :autoid=>1)[:items]
7
+ @c = Class.new(Sequel::Model(@ds))
8
+ @c.plugin :modification_detection
9
+ @c.columns :a, :b, :c, :d
10
+ @o = @c.first
11
+ @ds.db.sqls
12
+ end
13
+
14
+ it "should only detect columns that have been changed" do
15
+ @o.changed_columns.should == []
16
+ @o.a << 'b'
17
+ @o.changed_columns.should == [:a]
18
+ @o.a.replace('a')
19
+ @o.changed_columns.should == []
20
+
21
+ @o.values[:b] = 2
22
+ @o.changed_columns.should == [:b]
23
+ @o.values[:b] = 1
24
+ @o.changed_columns.should == []
25
+
26
+ @o.c[0] << 'b'
27
+ @o.d['b'] << 'b'
28
+ @o.changed_columns.sort_by{|c| c.to_s}.should == [:c, :d]
29
+ @o.c[0] = 'a'
30
+ @o.changed_columns.should == [:d]
31
+ @o.d['b'] = 'c'
32
+ @o.changed_columns.should == []
33
+ end
34
+
35
+ it "should not list a column twice" do
36
+ @o.a = 'b'
37
+ @o.a << 'a'
38
+ @o.changed_columns.should == [:a]
39
+ end
40
+
41
+ it "should report correct changed_columns after updating" do
42
+ @o.a << 'a'
43
+ @o.save_changes
44
+ @o.changed_columns.should == []
45
+
46
+ @o.values[:b] = 2
47
+ @o.save_changes
48
+ @o.changed_columns.should == []
49
+
50
+ @o.c[0] << 'b'
51
+ @o.save_changes
52
+ @o.changed_columns.should == []
53
+
54
+ @o.d['b'] << 'a'
55
+ @o.save_changes
56
+ @o.changed_columns.should == []
57
+
58
+ @ds.db.sqls.should == ["UPDATE items SET a = 'aa' WHERE (id = 1)",
59
+ "UPDATE items SET b = 2 WHERE (id = 1)",
60
+ "UPDATE items SET c = ('ab') WHERE (id = 1)",
61
+ "UPDATE items SET d = ('b' = 'ca') WHERE (id = 1)"]
62
+ end
63
+
64
+ it "should report correct changed_columns after creating new object" do
65
+ o = @c.create
66
+ o.changed_columns.should == []
67
+ o.a << 'a'
68
+ o.changed_columns.should == [:a]
69
+ @ds.db.sqls.should == ["INSERT INTO items DEFAULT VALUES", "SELECT * FROM items WHERE (id = 1) LIMIT 1"]
70
+ end
71
+
72
+ it "should report correct changed_columns after refreshing existing object" do
73
+ @o.a << 'a'
74
+ @o.changed_columns.should == [:a]
75
+ @o.refresh
76
+ @o.changed_columns.should == []
77
+ @o.a << 'a'
78
+ @o.changed_columns.should == [:a]
79
+ end
80
+ end
@@ -0,0 +1,64 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe "pg_inet extension" do
4
+ before do
5
+ @db = Sequel.connect('mock://postgres', :quote_identifiers=>false)
6
+ @db.extend(Module.new do
7
+ def schema_parse_table(*)
8
+ [[:a, {:oid=>1}]]
9
+ end
10
+ end)
11
+ @db.send(:metadata_dataset)._fetch = [[{:v=>1, :enumlabel=>'a'}, {:v=>1, :enumlabel=>'b'}, {:v=>1, :enumlabel=>'c'}],
12
+ [{:typname=>'enum1', :v=>212389}]]
13
+ @db.extension(:pg_array, :pg_enum)
14
+ @db.sqls
15
+ end
16
+
17
+ it "should include enum information in the schema entry" do
18
+ @db.schema(:a).should == [[:a, {:oid=>1, :ruby_default=>nil, :type=>:enum, :enum_values=>%w'a b c'}]]
19
+ end
20
+
21
+ it "should typecast objects to string" do
22
+ @db.typecast_value(:enum, :a).should == 'a'
23
+ end
24
+
25
+ it "should add array parsers for enum values" do
26
+ @db.conversion_procs[212389].call('{a,b,c}').should == %w'a b c'
27
+ end
28
+
29
+ it "should support #create_enum method for adding a new enum" do
30
+ @db.create_enum(:foo, [:a, :b, :c])
31
+ @db.sqls.first.should == "CREATE TYPE foo AS ENUM ('a', 'b', 'c')"
32
+ @db.create_enum(:sch__foo, %w'a b c')
33
+ @db.sqls.first.should == "CREATE TYPE sch.foo AS ENUM ('a', 'b', 'c')"
34
+ end
35
+
36
+ it "should support #drop_enum method for dropping an enum" do
37
+ @db.drop_enum(:foo)
38
+ @db.sqls.first.should == "DROP TYPE foo"
39
+ @db.drop_enum(:sch__foo, :if_exists=>true)
40
+ @db.sqls.first.should == "DROP TYPE IF EXISTS sch.foo"
41
+ @db.drop_enum('foo', :cascade=>true)
42
+ @db.sqls.first.should == "DROP TYPE foo CASCADE"
43
+ end
44
+
45
+ it "should support #add_enum_value method for adding value to an existing enum" do
46
+ @db.add_enum_value(:foo, :a)
47
+ @db.sqls.first.should == "ALTER TYPE foo ADD VALUE 'a'"
48
+ end
49
+
50
+ it "should support :before option for #add_enum_value method for adding value before an existing enum value" do
51
+ @db.add_enum_value('foo', :a, :before=>:b)
52
+ @db.sqls.first.should == "ALTER TYPE foo ADD VALUE 'a' BEFORE 'b'"
53
+ end
54
+
55
+ it "should support :after option for #add_enum_value method for adding value after an existing enum value" do
56
+ @db.add_enum_value(:sch__foo, :a, :after=>:b)
57
+ @db.sqls.first.should == "ALTER TYPE sch.foo ADD VALUE 'a' AFTER 'b'"
58
+ end
59
+
60
+ it "should support :if_not_exists option for #add_enum_value method for not adding the value if it exists" do
61
+ @db.add_enum_value(:foo, :a, :if_not_exists=>true)
62
+ @db.sqls.first.should == "ALTER TYPE foo ADD VALUE IF NOT EXISTS 'a'"
63
+ end
64
+ end
@@ -10,17 +10,6 @@ describe "pg_json extension" do
10
10
  @ac = m::JSONArray
11
11
  @bhc = m::JSONBHash
12
12
  @bac = m::JSONBArray
13
-
14
- # Create subclass in correct namespace for easily overriding methods
15
- j = m::JSON = JSON.dup
16
- j.instance_eval do
17
- Parser = JSON::Parser
18
- alias old_parse parse
19
- def parse(s)
20
- return 1 if s == '1'
21
- old_parse(s)
22
- end
23
- end
24
13
  end
25
14
  before do
26
15
  @db = Sequel.connect('mock://postgres', :quote_identifiers=>false)
@@ -64,10 +53,15 @@ describe "pg_json extension" do
64
53
  Sequel.instance_eval do
65
54
  alias pj parse_json
66
55
  def parse_json(v)
67
- v
56
+ {'1'=>1, "'a'"=>'a', 'true'=>true, 'false'=>false, 'null'=>nil, 'o'=>Object.new}.fetch(v){pj(v)}
68
57
  end
69
58
  end
70
- proc{@m.parse_json('1')}.should raise_error(Sequel::InvalidValue)
59
+ @m.parse_json('1').should == 1
60
+ @m.parse_json("'a'").should == 'a'
61
+ @m.parse_json('true').should == true
62
+ @m.parse_json('false').should == false
63
+ @m.parse_json('null').should == nil
64
+ proc{@m.parse_json('o')}.should raise_error(Sequel::InvalidValue)
71
65
  ensure
72
66
  Sequel.instance_eval do
73
67
  alias parse_json pj
@@ -38,13 +38,15 @@ describe "prepared_statements plugin" do
38
38
  def supports_insert_select?
39
39
  true
40
40
  end
41
+ def supports_returning?(type)
42
+ true
43
+ end
41
44
  def insert_select(h)
42
45
  self._fetch = {:id=>1, :name=>'foo', :i => 2}
43
- ds = opts[:returning] ? self : returning
44
- ds.server(:default).with_sql(:insert_sql, h).first
46
+ server(:default).with_sql_first(insert_select_sql(h))
45
47
  end
46
- def insert_sql(*)
47
- "#{super}#{" RETURNING #{opts[:returning] && !opts[:returning].empty? ? opts[:returning].map{|c| literal(c)}.join(', ') : '*'}" if opts.has_key?(:returning)}"
48
+ def insert_select_sql(*v)
49
+ "#{insert_sql(*v)} RETURNING #{(opts[:returning] && !opts[:returning].empty?) ? opts[:returning].map{|c| literal(c)}.join(', ') : '*'}"
48
50
  end
49
51
  end
50
52
  @c.create(:name=>'foo').should == @c.load(:id=>1, :name=>'foo', :i => 2)
@@ -0,0 +1,43 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ if RUBY_VERSION >= '1.9.0'
4
+ describe "Sequel::Dataset::RoundTimestamps" do
5
+ before do
6
+ @dataset = Sequel.mock.dataset.extension(:round_timestamps)
7
+ end
8
+
9
+ specify "should round times properly for databases supporting microsecond precision" do
10
+ @dataset.literal(Sequel::SQLTime.create(1, 2, 3, 499999.5)).should == "'01:02:03.500000'"
11
+ @dataset.literal(Time.local(2010, 1, 2, 3, 4, 5.4999995)).should == "'2010-01-02 03:04:05.500000'"
12
+ @dataset.literal(DateTime.new(2010, 1, 2, 3, 4, Rational(54999995, 10000000))).should == "'2010-01-02 03:04:05.500000'"
13
+
14
+ @dataset.literal(Sequel::SQLTime.create(1, 2, 3, 499999.4)).should == "'01:02:03.499999'"
15
+ @dataset.literal(Time.local(2010, 1, 2, 3, 4, 5.4999994)).should == "'2010-01-02 03:04:05.499999'"
16
+ @dataset.literal(DateTime.new(2010, 1, 2, 3, 4, Rational(54999994, 10000000))).should == "'2010-01-02 03:04:05.499999'"
17
+ end
18
+
19
+ specify "should round times properly for databases supporting millisecond precision" do
20
+ def @dataset.timestamp_precision() 3 end
21
+ @dataset.literal(Sequel::SQLTime.create(1, 2, 3, 499500)).should == "'01:02:03.500'"
22
+ @dataset.literal(Time.local(2010, 1, 2, 3, 4, 5.4995)).should == "'2010-01-02 03:04:05.500'"
23
+ @dataset.literal(DateTime.new(2010, 1, 2, 3, 4, Rational(54995, 10000))).should == "'2010-01-02 03:04:05.500'"
24
+
25
+ @dataset.literal(Sequel::SQLTime.create(1, 2, 3, 499499)).should == "'01:02:03.499'"
26
+ @dataset.literal(Time.local(2010, 1, 2, 3, 4, 5.4994)).should == "'2010-01-02 03:04:05.499'"
27
+ @dataset.literal(DateTime.new(2010, 1, 2, 3, 4, Rational(54994, 10000))).should == "'2010-01-02 03:04:05.499'"
28
+ end
29
+
30
+ specify "should round times properly for databases supporting second precision" do
31
+ def @dataset.supports_timestamp_usecs?() false end
32
+ @dataset.literal(Sequel::SQLTime.create(1, 2, 3, 500000)).should == "'01:02:04'"
33
+ @dataset.literal(Time.local(2010, 1, 2, 3, 4, 5.5)).should == "'2010-01-02 03:04:06'"
34
+ @dataset.literal(DateTime.new(2010, 1, 2, 3, 4, Rational(55, 10))).should == "'2010-01-02 03:04:06'"
35
+
36
+ @dataset.literal(Sequel::SQLTime.create(1, 2, 3, 499999)).should == "'01:02:03'"
37
+ @dataset.literal(Time.local(2010, 1, 2, 3, 4, 5.4999999)).should == "'2010-01-02 03:04:05'"
38
+ @dataset.literal(DateTime.new(2010, 1, 2, 3, 4, Rational(54999999, 10000000))).should == "'2010-01-02 03:04:05'"
39
+ end
40
+ end
41
+ else
42
+ skip_warn "round_timestamps extension: only works on ruby 1.9+"
43
+ end
@@ -78,7 +78,7 @@ describe "serialization_modification_detection plugin" do
78
78
  @o1.changed_columns.should == [:h]
79
79
  end
80
80
 
81
- it "should work with frozen objects" do
81
+ it "should work with duplicating objects" do
82
82
  @o2.changed_columns.should == []
83
83
  o = @o2.dup
84
84
  @o2.h.should == {}
@@ -86,4 +86,13 @@ describe "serialization_modification_detection plugin" do
86
86
  @o2.changed_columns.should == [:h]
87
87
  o.changed_columns.should == []
88
88
  end
89
+
90
+ it "should work with duplicating objects after modifying them" do
91
+ @o2.changed_columns.should == []
92
+ @o2.h.should == {}
93
+ @o2.h[1] = 2
94
+ @o2.changed_columns.should == [:h]
95
+ o = @o2.dup
96
+ o.changed_columns.should == [:h]
97
+ end
89
98
  end
@@ -26,6 +26,24 @@ describe "Serialization plugin" do
26
26
  DB.sqls.last.should =~ /INSERT INTO items \((ghi)\) VALUES \('\[123\]'\)/
27
27
  end
28
28
 
29
+ it "should handle validations of underlying column" do
30
+ @c.plugin :serialization, :yaml, :abc
31
+ o = @c.new
32
+ def o.validate
33
+ errors.add(:abc, "not present") unless self[:abc]
34
+ end
35
+ o.valid?.should == false
36
+ o.abc = {}
37
+ o.valid?.should == true
38
+ end
39
+
40
+ it "should set column values even when not validating" do
41
+ @c.set_primary_key :id
42
+ @c.plugin :serialization, :yaml, :abc
43
+ @c.load({:id=>1}).set(:abc=>{}).save(:validate=>false)
44
+ DB.sqls.last.gsub("\n", '').should == "UPDATE items SET abc = '--- {}' WHERE (id = 1)"
45
+ end
46
+
29
47
  it "should allow serializing attributes to yaml" do
30
48
  @c.plugin :serialization, :yaml, :abc
31
49
  @c.create(:abc => 1)
@@ -85,6 +85,11 @@ describe Sequel::Model, "single table inheritance plugin" do
85
85
  o.valid?.should == true
86
86
  end
87
87
 
88
+ it "should set type column field even if validations are skipped" do
89
+ StiTestSub1.new.save(:validate=>false)
90
+ DB.sqls.should == ["INSERT INTO sti_tests (kind) VALUES ('StiTestSub1')", "SELECT * FROM sti_tests WHERE ((sti_tests.kind IN ('StiTestSub1')) AND (id = 10)) LIMIT 1"]
91
+ end
92
+
88
93
  it "should override an existing value in the class name field" do
89
94
  StiTest.create(:kind=>'StiTestSub1')
90
95
  DB.sqls.should == ["INSERT INTO sti_tests (kind) VALUES ('StiTestSub1')", "SELECT * FROM sti_tests WHERE (id = 10) LIMIT 1"]
@@ -32,6 +32,12 @@ describe "Sequel::Plugins::Timestamps" do
32
32
  o.valid?.should == true
33
33
  end
34
34
 
35
+ it "should set timestamp fields when skipping validations" do
36
+ @c.plugin :timestamps
37
+ @c.new.save(:validate=>false)
38
+ @c.db.sqls.should == ["INSERT INTO t (created_at) VALUES ('2009-08-01')"]
39
+ end
40
+
35
41
  it "should set the create timestamp field on creation" do
36
42
  o = @c.create
37
43
  @c.db.sqls.should == ["INSERT INTO t (created_at) VALUES ('2009-08-01')"]
@@ -1,8 +1,5 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
2
 
3
- # DB2 does not seem to support USING joins in every version; it seems to be
4
- # valid expression in DB2 iSeries UDB though.
5
- unless !DB.dataset.supports_join_using? || Sequel.guarded?(:db2)
6
3
  describe "Class Table Inheritance Plugin" do
7
4
  before(:all) do
8
5
  @db = DB
@@ -37,7 +34,7 @@ describe "Class Table Inheritance Plugin" do
37
34
  class ::Executive < Manager
38
35
  end
39
36
  class ::Staff < Employee
40
- many_to_one :manager, :qualify=>false
37
+ many_to_one :manager
41
38
  end
42
39
 
43
40
  @i1 =@db[:employees].insert(:name=>'E', :kind=>'Employee')
@@ -96,10 +93,10 @@ describe "Class Table Inheritance Plugin" do
96
93
  end
97
94
 
98
95
  specify "should handle associations only defined in subclasses" do
99
- Employee.filter(:id=>@i2).all.first.manager.id.should == @i4
96
+ Employee.filter(:employees__id=>@i2).all.first.manager.id.should == @i4
100
97
  end
101
98
 
102
- cspecify "should insert rows into all tables", [proc{|db| db.sqlite_version < 30709}, :sqlite] do
99
+ specify "should insert rows into all tables" do
103
100
  e = Executive.create(:name=>'Ex2', :num_managers=>8, :num_staff=>9)
104
101
  i = e.id
105
102
  @db[:employees][:id=>i].should == {:id=>i, :name=>'Ex2', :kind=>'Executive'}
@@ -138,13 +135,12 @@ describe "Class Table Inheritance Plugin" do
138
135
  Executive.limit(1).eager(:staff_members).first.staff_members.should == [Staff[@i2]]
139
136
  end
140
137
 
141
- cspecify "should handle eagerly graphing one_to_many relationships", [proc{|db| db.sqlite_version < 30709}, :sqlite] do
138
+ specify "should handle eagerly graphing one_to_many relationships" do
142
139
  es = Executive.limit(1).eager_graph(:staff_members).all
143
140
  es.should == [Executive[@i4]]
144
141
  es.map{|x| x.staff_members}.should == [[Staff[@i2]]]
145
142
  end
146
143
  end
147
- end
148
144
 
149
145
  describe "Many Through Many Plugin" do
150
146
  before(:all) do
@@ -1494,6 +1490,11 @@ describe "List plugin without a scope" do
1494
1490
  proc { @c[:name => "def"].move_up(10) }.should raise_error(Sequel::Error)
1495
1491
  proc { @c[:name => "def"].move_down(10) }.should raise_error(Sequel::Error)
1496
1492
  end
1493
+
1494
+ it "should update positions on destroy" do
1495
+ @c[:name => "def"].destroy
1496
+ @c.select_map([:position, :name]).should == [[1, 'abc'], [2, 'hig']]
1497
+ end
1497
1498
  end
1498
1499
 
1499
1500
  describe "List plugin with a scope" do
@@ -1572,6 +1573,11 @@ describe "List plugin with a scope" do
1572
1573
  proc { @c[:name => "P1"].move_up(10) }.should raise_error(Sequel::Error)
1573
1574
  proc { @c[:name => "P1"].move_down(10) }.should raise_error(Sequel::Error)
1574
1575
  end
1576
+
1577
+ it "should update positions on destroy" do
1578
+ @c[:name => "P2"].destroy
1579
+ @c.select_order_map([:pos, :name]).should == [[1, "Hm"], [1, "P1"], [1, "Ps"], [2, "Au"], [2, "P3"]]
1580
+ end
1575
1581
  end
1576
1582
 
1577
1583
  describe "Sequel::Plugins::Tree" do
@@ -117,6 +117,12 @@ describe "Prepared Statements and Bound Arguments" do
117
117
  @ds.filter(:id=>2).first[:numb].should == 20
118
118
  end
119
119
 
120
+ specify "should support bound variables with insert_select" do
121
+ @ds.call(:insert_select, {:n=>20}, :numb=>:$n).should == {:id=>2, :numb=>20}
122
+ @ds.count.should == 2
123
+ @ds.order(:id).map(:numb).should == [10, 20]
124
+ end if DB.dataset.supports_insert_select?
125
+
120
126
  specify "should support bound variables with delete" do
121
127
  @ds.filter(:numb=>:$n).call(:delete, :n=>10).should == 1
122
128
  @ds.count.should == 0
@@ -228,6 +234,12 @@ describe "Prepared Statements and Bound Arguments" do
228
234
  @ds.filter(:id=>2).first[:numb].should == 20
229
235
  end
230
236
 
237
+ specify "should support prepared_statements with insert_select" do
238
+ @ds.prepare(:insert_select, :insert_select_n, :numb=>:$n).call(:n=>20).should == {:id=>2, :numb=>20}
239
+ @ds.count.should == 2
240
+ @ds.order(:id).map(:numb).should == [10, 20]
241
+ end if DB.dataset.supports_insert_select?
242
+
231
243
  specify "should support prepared statements with delete" do
232
244
  @ds.filter(:numb=>:$n).prepare(:delete, :delete_n)
233
245
  @db.call(:delete_n, :n=>10).should == 1
@@ -1890,6 +1890,30 @@ describe Sequel::Model, "many_to_many" do
1890
1890
  end
1891
1891
  end
1892
1892
 
1893
+ it "should not override a selection consisting completely of qualified columns using Sequel::SQL::QualifiedIdentifier" do
1894
+ @c1.dataset = @c1.dataset.select(Sequel.qualify(:attributes, :id), Sequel.qualify(:attributes, :b))
1895
+ @c2.many_to_many :attributes, :class => @c1
1896
+ @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.id, attributes.b FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)'
1897
+ end
1898
+
1899
+ it "should not override a selection consisting completely of qualified columns using symbols" do
1900
+ @c1.dataset = @c1.dataset.select(:attributes__id, :attributes__b)
1901
+ @c2.many_to_many :attributes, :class => @c1
1902
+ @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.id, attributes.b FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)'
1903
+ end
1904
+
1905
+ it "should not override a selection consisting completely of qualified columns using Sequel::SQL::AliasedExpression" do
1906
+ @c1.dataset = @c1.dataset.select(Sequel.qualify(:attributes, :id).as(:a), Sequel.as(:attributes__b, :c))
1907
+ @c2.many_to_many :attributes, :class => @c1
1908
+ @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.id AS a, attributes.b AS c FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)'
1909
+ end
1910
+
1911
+ it "should override a selection consisting of non qualified columns" do
1912
+ @c1.dataset = @c1.dataset.select{foo(:bar)}
1913
+ @c2.many_to_many :attributes, :class => @c1
1914
+ @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)'
1915
+ end
1916
+
1893
1917
  it "should respect :eager_loader_predicate_key when lazily loading" do
1894
1918
  @c2.many_to_many :attributes, :class => @c1, :eager_loading_predicate_key=>Sequel.subscript(:attributes_nodes__node_id, 0)
1895
1919
  @c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id[0] = 1234)'