sequel 5.3.0 → 5.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG +30 -0
- data/bin/sequel +13 -0
- data/doc/cheat_sheet.rdoc +1 -0
- data/doc/dataset_filtering.rdoc +1 -1
- data/doc/querying.rdoc +8 -11
- data/doc/release_notes/5.4.0.txt +80 -0
- data/doc/testing.rdoc +2 -0
- data/lib/sequel/adapters/shared/db2.rb +6 -5
- data/lib/sequel/adapters/shared/mssql.rb +5 -8
- data/lib/sequel/adapters/shared/mysql.rb +4 -8
- data/lib/sequel/adapters/shared/oracle.rb +1 -1
- data/lib/sequel/adapters/shared/postgres.rb +5 -3
- data/lib/sequel/adapters/shared/sqlanywhere.rb +1 -6
- data/lib/sequel/adapters/shared/sqlite.rb +2 -0
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/schema_methods.rb +10 -1
- data/lib/sequel/dataset/query.rb +1 -2
- data/lib/sequel/extensions/date_arithmetic.rb +27 -10
- data/lib/sequel/extensions/datetime_parse_to_time.rb +37 -0
- data/lib/sequel/extensions/index_caching.rb +107 -0
- data/lib/sequel/extensions/null_dataset.rb +3 -1
- data/lib/sequel/extensions/pg_timestamptz.rb +26 -0
- data/lib/sequel/model/base.rb +2 -2
- data/lib/sequel/plugins/class_table_inheritance.rb +11 -3
- data/lib/sequel/plugins/json_serializer.rb +2 -2
- data/lib/sequel/plugins/xml_serializer.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/postgres_spec.rb +1 -1
- data/spec/adapters/spec_helper.rb +3 -0
- data/spec/adapters/sqlite_spec.rb +1 -1
- data/spec/bin_spec.rb +9 -0
- data/spec/core/connection_pool_spec.rb +2 -2
- data/spec/core/dataset_spec.rb +1 -6
- data/spec/extensions/class_table_inheritance_spec.rb +52 -2
- data/spec/extensions/date_arithmetic_spec.rb +15 -1
- data/spec/extensions/datetime_parse_to_time_spec.rb +169 -0
- data/spec/extensions/index_caching_spec.rb +66 -0
- data/spec/extensions/json_serializer_spec.rb +5 -0
- data/spec/extensions/null_dataset_spec.rb +5 -0
- data/spec/extensions/pg_extended_date_support_spec.rb +4 -0
- data/spec/extensions/pg_timestamptz_spec.rb +17 -0
- data/spec/extensions/xml_serializer_spec.rb +7 -0
- data/spec/integration/dataset_test.rb +6 -0
- data/spec/integration/prepared_statement_test.rb +1 -1
- data/spec/integration/schema_test.rb +19 -17
- data/spec/integration/spec_helper.rb +4 -0
- data/spec/model/record_spec.rb +28 -0
- metadata +11 -3
@@ -87,6 +87,10 @@ describe "date_arithmetic extension" do
|
|
87
87
|
db.literal(Sequel.date_add(:a, @h0)).must_equal "CAST(a AS timestamp)"
|
88
88
|
db.literal(Sequel.date_add(:a, @h1)).must_equal "(CAST(a AS timestamp) + CAST('1 days ' AS interval))"
|
89
89
|
db.literal(Sequel.date_add(:a, @h2)).must_equal "(CAST(a AS timestamp) + CAST('1 years 1 months 1 days 1 hours 1 minutes 1 seconds ' AS interval))"
|
90
|
+
|
91
|
+
db.literal(Sequel.date_add(:a, @h0, :cast=>:timestamptz)).must_equal "CAST(a AS timestamptz)"
|
92
|
+
db.literal(Sequel.date_sub(:a, @h0, :cast=>:timestamptz)).must_equal "CAST(a AS timestamptz)"
|
93
|
+
db.literal(Sequel.date_add(:a, @h2, :cast=>:timestamptz)).must_equal "(CAST(a AS timestamptz) + CAST('1 years 1 months 1 days 1 hours 1 minutes 1 seconds ' AS interval))"
|
90
94
|
end
|
91
95
|
|
92
96
|
it "should correctly literalize on SQLite" do
|
@@ -101,6 +105,7 @@ describe "date_arithmetic extension" do
|
|
101
105
|
db.literal(Sequel.date_add(:a, @h0)).must_equal "CAST(a AS DATETIME)"
|
102
106
|
db.literal(Sequel.date_add(:a, @h1)).must_equal "DATE_ADD(a, INTERVAL 1 DAY)"
|
103
107
|
db.literal(Sequel.date_add(:a, @h2)).must_equal "DATE_ADD(DATE_ADD(DATE_ADD(DATE_ADD(DATE_ADD(DATE_ADD(a, INTERVAL 1 YEAR), INTERVAL 1 MONTH), INTERVAL 1 DAY), INTERVAL 1 HOUR), INTERVAL 1 MINUTE), INTERVAL 1 SECOND)"
|
108
|
+
db.literal(Sequel.date_add(:a, @h0, :cast=>:timestamp)).must_equal "CAST(a AS timestamp)"
|
104
109
|
end
|
105
110
|
|
106
111
|
it "should correctly literalize on HSQLDB" do
|
@@ -110,6 +115,9 @@ describe "date_arithmetic extension" do
|
|
110
115
|
db.literal(Sequel.date_add(:a, @h0)).must_equal "CAST(CAST(a AS timestamp) AS timestamp)"
|
111
116
|
db.literal(Sequel.date_add(:a, @h1)).must_equal "DATE_ADD(CAST(a AS timestamp), INTERVAL 1 DAY)"
|
112
117
|
db.literal(Sequel.date_add(:a, @h2)).must_equal "DATE_ADD(DATE_ADD(DATE_ADD(DATE_ADD(DATE_ADD(DATE_ADD(CAST(a AS timestamp), INTERVAL 1 YEAR), INTERVAL 1 MONTH), INTERVAL 1 DAY), INTERVAL 1 HOUR), INTERVAL 1 MINUTE), INTERVAL 1 SECOND)"
|
118
|
+
|
119
|
+
db.literal(Sequel.date_add(:a, @h0, :cast=>:datetime)).must_equal "CAST(CAST(a AS datetime) AS datetime)"
|
120
|
+
db.literal(Sequel.date_add(:a, @h2, :cast=>:datetime)).must_equal "DATE_ADD(DATE_ADD(DATE_ADD(DATE_ADD(DATE_ADD(DATE_ADD(CAST(a AS datetime), INTERVAL 1 YEAR), INTERVAL 1 MONTH), INTERVAL 1 DAY), INTERVAL 1 HOUR), INTERVAL 1 MINUTE), INTERVAL 1 SECOND)"
|
113
121
|
end
|
114
122
|
|
115
123
|
it "should correctly literalize on MSSQL" do
|
@@ -117,6 +125,7 @@ describe "date_arithmetic extension" do
|
|
117
125
|
db.literal(Sequel.date_add(:A, @h0)).must_equal "CAST(A AS datetime)"
|
118
126
|
db.literal(Sequel.date_add(:A, @h1)).must_equal "DATEADD(day, 1, A)"
|
119
127
|
db.literal(Sequel.date_add(:A, @h2)).must_equal "DATEADD(second, 1, DATEADD(minute, 1, DATEADD(hour, 1, DATEADD(day, 1, DATEADD(month, 1, DATEADD(year, 1, A))))))"
|
128
|
+
db.literal(Sequel.date_add(:A, @h0, :cast=>:timestamp)).must_equal "CAST(A AS timestamp)"
|
120
129
|
end
|
121
130
|
|
122
131
|
it "should correctly literalize on H2" do
|
@@ -126,6 +135,7 @@ describe "date_arithmetic extension" do
|
|
126
135
|
db.literal(Sequel.date_add(:a, @h0)).must_equal "CAST(a AS timestamp)"
|
127
136
|
db.literal(Sequel.date_add(:a, @h1)).must_equal "DATEADD('day', 1, a)"
|
128
137
|
db.literal(Sequel.date_add(:a, @h2)).must_equal "DATEADD('second', 1, DATEADD('minute', 1, DATEADD('hour', 1, DATEADD('day', 1, DATEADD('month', 1, DATEADD('year', 1, a))))))"
|
138
|
+
db.literal(Sequel.date_add(:a, @h0, :cast=>:datetime)).must_equal "CAST(a AS datetime)"
|
129
139
|
end
|
130
140
|
|
131
141
|
it "should correctly literalize on access" do
|
@@ -143,6 +153,7 @@ describe "date_arithmetic extension" do
|
|
143
153
|
db.literal(Sequel.date_add(:a, @h1)).must_equal "{fn timestampadd(SQL_TSI_DAY, 1, timestamp(a))}"
|
144
154
|
db.literal(Sequel.date_add(:a, @h2)).must_equal "{fn timestampadd(SQL_TSI_SECOND, 1, timestamp({fn timestampadd(SQL_TSI_MINUTE, 1, timestamp({fn timestampadd(SQL_TSI_HOUR, 1, timestamp({fn timestampadd(SQL_TSI_DAY, 1, timestamp({fn timestampadd(SQL_TSI_MONTH, 1, timestamp({fn timestampadd(SQL_TSI_YEAR, 1, timestamp(a))}))}))}))}))}))}"
|
145
155
|
db.literal(Sequel.date_add(Date.civil(2012, 11, 12), @h1)).must_equal "{fn timestampadd(SQL_TSI_DAY, 1, timestamp((CAST('2012-11-12' AS varchar(255)) || ' 00:00:00')))}"
|
156
|
+
db.literal(Sequel.date_add(:a, @h0, :cast=>:datetime)).must_equal "CAST(a AS datetime)"
|
146
157
|
end
|
147
158
|
|
148
159
|
it "should correctly literalize on Oracle" do
|
@@ -150,13 +161,16 @@ describe "date_arithmetic extension" do
|
|
150
161
|
db.literal(Sequel.date_add(:A, @h0)).must_equal "CAST(A AS timestamp)"
|
151
162
|
db.literal(Sequel.date_add(:A, @h1)).must_equal "(A + INTERVAL '1' DAY)"
|
152
163
|
db.literal(Sequel.date_add(:A, @h2)).must_equal "(A + INTERVAL '1' YEAR + INTERVAL '1' MONTH + INTERVAL '1' DAY + INTERVAL '1' HOUR + INTERVAL '1' MINUTE + INTERVAL '1' SECOND)"
|
164
|
+
db.literal(Sequel.date_add(:A, @h0, :cast=>:datetime)).must_equal "CAST(A AS datetime)"
|
153
165
|
end
|
154
166
|
|
155
167
|
it "should correctly literalize on DB2" do
|
156
168
|
db = dbf.call(:db2)
|
157
169
|
db.literal(Sequel.date_add(:A, @h0)).must_equal "CAST(A AS timestamp)"
|
158
170
|
db.literal(Sequel.date_add(:A, @h1)).must_equal "(CAST(A AS timestamp) + 1 days)"
|
159
|
-
db.literal(Sequel.date_add(:A, @
|
171
|
+
db.literal(Sequel.date_add(:A, @h0)).must_equal "CAST(A AS timestamp)"
|
172
|
+
db.literal(Sequel.date_add(:A, @h1, :cast=>:datetime)).must_equal "(CAST(A AS datetime) + 1 days)"
|
173
|
+
db.literal(Sequel.date_add(:A, @h2, :cast=>:datetime)).must_equal "(CAST(A AS datetime) + 1 years + 1 months + 1 days + 1 hours + 1 minutes + 1 seconds)"
|
160
174
|
end
|
161
175
|
|
162
176
|
it "should raise error if literalizing on an unsupported database" do
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
describe "datetime_parse_to_time extension" do
|
4
|
+
before(:all) do
|
5
|
+
Sequel.extension :datetime_parse_to_time
|
6
|
+
end
|
7
|
+
after(:all) do
|
8
|
+
# Can't undo the adding of the module to Sequel, so removing the
|
9
|
+
# method in the module is the only way to fix it.
|
10
|
+
Sequel::DateTimeParseToTime.send(:remove_method, :convert_input_timestamp)
|
11
|
+
end
|
12
|
+
|
13
|
+
before do
|
14
|
+
@db = Sequel::Database.new
|
15
|
+
@dataset = @db.dataset.with_extend do
|
16
|
+
def supports_timestamp_timezones?; true end
|
17
|
+
def supports_timestamp_usecs?; false end
|
18
|
+
end
|
19
|
+
@utc_time = Time.utc(2010, 1, 2, 3, 4, 5)
|
20
|
+
@local_time = Time.local(2010, 1, 2, 3, 4, 5)
|
21
|
+
@offset = sprintf("%+03i%02i", *(@local_time.utc_offset/60).divmod(60))
|
22
|
+
@dt_offset = @local_time.utc_offset/Rational(86400, 1)
|
23
|
+
@utc_datetime = DateTime.new(2010, 1, 2, 3, 4, 5)
|
24
|
+
@local_datetime = DateTime.new(2010, 1, 2, 3, 4, 5, @dt_offset)
|
25
|
+
end
|
26
|
+
after do
|
27
|
+
Sequel.default_timezone = nil
|
28
|
+
Sequel.datetime_class = Time
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should handle conversions during invalid localtimes" do
|
32
|
+
# This only checks of a couple of times that may be invalid.
|
33
|
+
# You can run with TZ=Europe/Berlin or TZ=US/Pacific
|
34
|
+
Sequel.database_timezone = :utc
|
35
|
+
Sequel.database_to_application_timestamp("2017-03-26 02:30:00").getutc.hour.must_equal 2
|
36
|
+
Sequel.database_to_application_timestamp("2017-03-12 02:30:00").getutc.hour.must_equal 2
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should handle an database timezone of :utc when literalizing values" do
|
40
|
+
Sequel.database_timezone = :utc
|
41
|
+
@dataset.literal(Time.utc(2010, 1, 2, 3, 4, 5)).must_equal "'2010-01-02 03:04:05+0000'"
|
42
|
+
@dataset.literal(DateTime.new(2010, 1, 2, 3, 4, 5)).must_equal "'2010-01-02 03:04:05+0000'"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should handle an database timezone of :local when literalizing values" do
|
46
|
+
Sequel.database_timezone = :local
|
47
|
+
@dataset.literal(Time.local(2010, 1, 2, 3, 4, 5)).must_equal "'2010-01-02 03:04:05#{@offset}'"
|
48
|
+
@dataset.literal(DateTime.new(2010, 1, 2, 3, 4, 5, @dt_offset)).must_equal "'2010-01-02 03:04:05#{@offset}'"
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should have Database#timezone override Sequel.database_timezone" do
|
52
|
+
Sequel.database_timezone = :local
|
53
|
+
@db.timezone = :utc
|
54
|
+
@dataset.literal(Time.utc(2010, 1, 2, 3, 4, 5)).must_equal "'2010-01-02 03:04:05+0000'"
|
55
|
+
@dataset.literal(DateTime.new(2010, 1, 2, 3, 4, 5)).must_equal "'2010-01-02 03:04:05+0000'"
|
56
|
+
|
57
|
+
Sequel.database_timezone = :utc
|
58
|
+
@db.timezone = :local
|
59
|
+
@dataset.literal(Time.local(2010, 1, 2, 3, 4, 5)).must_equal "'2010-01-02 03:04:05#{@offset}'"
|
60
|
+
@dataset.literal(DateTime.new(2010, 1, 2, 3, 4, 5, @dt_offset)).must_equal "'2010-01-02 03:04:05#{@offset}'"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should handle converting database timestamps into application timestamps" do
|
64
|
+
Sequel.database_timezone = :utc
|
65
|
+
Sequel.application_timezone = :local
|
66
|
+
t = Time.now.utc
|
67
|
+
Sequel.database_to_application_timestamp(t).to_s.must_equal t.getlocal.to_s
|
68
|
+
Sequel.database_to_application_timestamp(t.to_s).to_s.must_equal t.getlocal.to_s
|
69
|
+
Sequel.database_to_application_timestamp(t.strftime('%Y-%m-%d %H:%M:%S')).to_s.must_equal t.getlocal.to_s
|
70
|
+
|
71
|
+
Sequel.datetime_class = DateTime
|
72
|
+
dt = DateTime.now
|
73
|
+
dt2 = dt.new_offset(0)
|
74
|
+
Sequel.database_to_application_timestamp(dt2).to_s.must_equal dt.to_s
|
75
|
+
Sequel.database_to_application_timestamp(dt2.to_s).to_s.must_equal dt.to_s
|
76
|
+
Sequel.database_to_application_timestamp(dt2.strftime('%Y-%m-%d %H:%M:%S')).to_s.must_equal dt.to_s
|
77
|
+
|
78
|
+
Sequel.datetime_class = Time
|
79
|
+
Sequel.database_timezone = :local
|
80
|
+
Sequel.application_timezone = :utc
|
81
|
+
Sequel.database_to_application_timestamp(t.getlocal).to_s.must_equal t.to_s
|
82
|
+
Sequel.database_to_application_timestamp(t.getlocal.to_s).to_s.must_equal t.to_s
|
83
|
+
Sequel.database_to_application_timestamp(t.getlocal.strftime('%Y-%m-%d %H:%M:%S')).to_s.must_equal t.to_s
|
84
|
+
|
85
|
+
Sequel.datetime_class = DateTime
|
86
|
+
Sequel.database_to_application_timestamp(dt).to_s.must_equal dt2.to_s
|
87
|
+
Sequel.database_to_application_timestamp(dt.to_s).to_s.must_equal dt2.to_s
|
88
|
+
Sequel.database_to_application_timestamp(dt.strftime('%Y-%m-%d %H:%M:%S')).to_s.must_equal dt2.to_s
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should handle typecasting timestamp columns" do
|
92
|
+
Sequel.typecast_timezone = :utc
|
93
|
+
Sequel.application_timezone = :local
|
94
|
+
t = Time.now.utc
|
95
|
+
@db.typecast_value(:datetime, t).to_s.must_equal t.getlocal.to_s
|
96
|
+
@db.typecast_value(:datetime, t.to_s).to_s.must_equal t.getlocal.to_s
|
97
|
+
@db.typecast_value(:datetime, t.strftime('%Y-%m-%d %H:%M:%S')).to_s.must_equal t.getlocal.to_s
|
98
|
+
|
99
|
+
Sequel.datetime_class = DateTime
|
100
|
+
dt = DateTime.now
|
101
|
+
dt2 = dt.new_offset(0)
|
102
|
+
@db.typecast_value(:datetime, dt2).to_s.must_equal dt.to_s
|
103
|
+
@db.typecast_value(:datetime, dt2.to_s).to_s.must_equal dt.to_s
|
104
|
+
@db.typecast_value(:datetime, dt2.strftime('%Y-%m-%d %H:%M:%S')).to_s.must_equal dt.to_s
|
105
|
+
|
106
|
+
Sequel.datetime_class = Time
|
107
|
+
Sequel.typecast_timezone = :local
|
108
|
+
Sequel.application_timezone = :utc
|
109
|
+
@db.typecast_value(:datetime, t.getlocal).to_s.must_equal t.to_s
|
110
|
+
@db.typecast_value(:datetime, t.getlocal.to_s).to_s.must_equal t.to_s
|
111
|
+
@db.typecast_value(:datetime, t.getlocal.strftime('%Y-%m-%d %H:%M:%S')).to_s.must_equal t.to_s
|
112
|
+
|
113
|
+
Sequel.datetime_class = DateTime
|
114
|
+
@db.typecast_value(:datetime, dt).to_s.must_equal dt2.to_s
|
115
|
+
@db.typecast_value(:datetime, dt.to_s).to_s.must_equal dt2.to_s
|
116
|
+
@db.typecast_value(:datetime, dt.strftime('%Y-%m-%d %H:%M:%S')).to_s.must_equal dt2.to_s
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should handle converting database timestamp columns from an array of values" do
|
120
|
+
Sequel.database_timezone = :utc
|
121
|
+
Sequel.application_timezone = :local
|
122
|
+
t = Time.now.utc
|
123
|
+
Sequel.database_to_application_timestamp([t.year, t.mon, t.day, t.hour, t.min, t.sec]).to_s.must_equal t.getlocal.to_s
|
124
|
+
|
125
|
+
Sequel.datetime_class = DateTime
|
126
|
+
dt = DateTime.now
|
127
|
+
dt2 = dt.new_offset(0)
|
128
|
+
Sequel.database_to_application_timestamp([dt2.year, dt2.mon, dt2.day, dt2.hour, dt2.min, dt2.sec]).to_s.must_equal dt.to_s
|
129
|
+
|
130
|
+
Sequel.datetime_class = Time
|
131
|
+
Sequel.database_timezone = :local
|
132
|
+
Sequel.application_timezone = :utc
|
133
|
+
t = t.getlocal
|
134
|
+
Sequel.database_to_application_timestamp([t.year, t.mon, t.day, t.hour, t.min, t.sec]).to_s.must_equal t.getutc.to_s
|
135
|
+
|
136
|
+
Sequel.datetime_class = DateTime
|
137
|
+
Sequel.database_to_application_timestamp([dt.year, dt.mon, dt.day, dt.hour, dt.min, dt.sec]).to_s.must_equal dt2.to_s
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should raise an InvalidValue error when an error occurs while converting a timestamp" do
|
141
|
+
proc{Sequel.database_to_application_timestamp([0, 0, 0, 0, 0, 0])}.must_raise(Sequel::InvalidValue)
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should raise an error when attempting to typecast to a timestamp from an unsupported type" do
|
145
|
+
proc{Sequel.database_to_application_timestamp(Object.new)}.must_raise(Sequel::InvalidValue)
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should raise an InvalidValue error when the DateTime class is used and when a bad application timezone is used when attempting to convert timestamps" do
|
149
|
+
Sequel.application_timezone = :blah
|
150
|
+
Sequel.datetime_class = DateTime
|
151
|
+
proc{Sequel.database_to_application_timestamp('2009-06-01 10:20:30')}.must_raise(Sequel::InvalidValue)
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should raise an InvalidValue error when the DateTime class is used and when a bad database timezone is used when attempting to convert timestamps" do
|
155
|
+
Sequel.database_timezone = :blah
|
156
|
+
Sequel.datetime_class = DateTime
|
157
|
+
proc{Sequel.database_to_application_timestamp('2009-06-01 10:20:30')}.must_raise(Sequel::InvalidValue)
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should have Sequel.default_timezone= should set all other timezones" do
|
161
|
+
Sequel.database_timezone.must_be_nil
|
162
|
+
Sequel.application_timezone.must_be_nil
|
163
|
+
Sequel.typecast_timezone.must_be_nil
|
164
|
+
Sequel.default_timezone = :utc
|
165
|
+
Sequel.database_timezone.must_equal :utc
|
166
|
+
Sequel.application_timezone.must_equal :utc
|
167
|
+
Sequel.typecast_timezone.must_equal :utc
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
describe "index_caching extension" do
|
4
|
+
before do
|
5
|
+
@db = Sequel.connect('mock://postgres').extension(:index_caching)
|
6
|
+
@indexes = {'"table"'=>{:table_idx_unique=>{:columns=>[:first_col, :second_col], :unique=>true, :deferrable=>nil}}}
|
7
|
+
@filename = "spec/files/test_indexes_#$$.dump"
|
8
|
+
@db.instance_variable_set(:@indexes, @indexes)
|
9
|
+
end
|
10
|
+
after do
|
11
|
+
File.delete(@filename) if File.exist?(@filename)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "#indexes should return cached index information" do
|
15
|
+
@db.indexes(:table).must_equal @indexes['"table"']
|
16
|
+
@db.indexes(:table, {}).must_equal @indexes['"table"']
|
17
|
+
end
|
18
|
+
|
19
|
+
it "#indexes should skip cached information if given options" do
|
20
|
+
@db.indexes(:table, :schema=>:b).must_equal({})
|
21
|
+
end
|
22
|
+
|
23
|
+
it "Database should remove cached indexes when schema is changed" do
|
24
|
+
@db.create_table(:table){Integer :a}
|
25
|
+
@db.indexes(:table).must_equal({})
|
26
|
+
end
|
27
|
+
|
28
|
+
it "Database#freeze should allow cached information to work" do
|
29
|
+
@db.freeze.indexes(:table).must_equal @indexes['"table"']
|
30
|
+
end
|
31
|
+
|
32
|
+
it "Database#freeze should allow removing index information" do
|
33
|
+
@db.freeze
|
34
|
+
@db.create_table(:table){Integer :a}
|
35
|
+
@db.indexes(:table).must_equal({})
|
36
|
+
end
|
37
|
+
|
38
|
+
it "Database#dump_index_cache should dump the index cache to the given file" do
|
39
|
+
File.exist?(@filename).must_equal false
|
40
|
+
@db.dump_index_cache(@filename)
|
41
|
+
File.exist?(@filename).must_equal true
|
42
|
+
File.size(@filename).must_be :>, 0
|
43
|
+
end
|
44
|
+
|
45
|
+
it "Database#load_index_cache should load the index cache from the given file dumped by #dump_index_cache" do
|
46
|
+
@db.dump_index_cache(@filename)
|
47
|
+
db = Sequel::Database.new.extension(:index_caching)
|
48
|
+
db.load_index_cache(@filename)
|
49
|
+
db.extension(:index_caching)
|
50
|
+
@db.instance_variable_get(:@indexes).must_equal @indexes
|
51
|
+
end
|
52
|
+
|
53
|
+
it "Database#dump_index_cache? should dump the index cache to the given file unless the file exists" do
|
54
|
+
File.open(@filename, 'wb'){|f|}
|
55
|
+
File.size(@filename).must_equal 0
|
56
|
+
@db.dump_index_cache?(@filename)
|
57
|
+
File.size(@filename).must_equal 0
|
58
|
+
end
|
59
|
+
|
60
|
+
it "Database#load_index_cache? should load the index cache from the given file if it exists" do
|
61
|
+
db = Sequel::Database.new.extension(:index_caching)
|
62
|
+
File.exist?(@filename).must_equal false
|
63
|
+
db.load_index_cache?(@filename)
|
64
|
+
db.instance_variable_get(:@indexes).must_equal({})
|
65
|
+
end
|
66
|
+
end
|
@@ -187,6 +187,11 @@ describe "Sequel::Plugins::JsonSerializer" do
|
|
187
187
|
Album.array_from_json(Album.dataset.to_json(:only=>:name)).must_equal [Album.load(:name=>@album.name)]
|
188
188
|
end
|
189
189
|
|
190
|
+
it "should have dataset to_json method work with eager_graph datasets" do
|
191
|
+
ds = Album.dataset.eager_graph(:artist).with_fetch(:id=>1, :name=>'RF', :artist_id=>2, :artist_id_0=>2, :artist_name=>'YM')
|
192
|
+
Sequel.parse_json(ds.to_json(:only=>:name, :include=>{:artist=>{:only=>:name}})).must_equal [{"name"=>"RF", "artist"=>{"name"=>"YM"}}]
|
193
|
+
end
|
194
|
+
|
190
195
|
it "should have dataset to_json method work with naked datasets" do
|
191
196
|
ds = Album.dataset.naked.with_fetch(:id=>1, :name=>'RF', :artist_id=>2)
|
192
197
|
Sequel.parse_json(ds.to_json).must_equal [@album.values.inject({}){|h, (k, v)| h[k.to_s] = v; h}]
|
@@ -21,6 +21,11 @@ describe "null_dataset extension" do
|
|
21
21
|
@i.must_equal 0
|
22
22
|
end
|
23
23
|
|
24
|
+
it "nullify should be a cached dataset" do
|
25
|
+
ds = @db[:table]
|
26
|
+
ds.nullify.object_id.must_equal(ds.nullify.object_id)
|
27
|
+
end
|
28
|
+
|
24
29
|
it "should make insert be a noop" do
|
25
30
|
@ds.insert(1).must_be_nil
|
26
31
|
end
|
@@ -105,6 +105,10 @@ describe "pg_extended_date_support extension" do
|
|
105
105
|
@db.literal(-Date::Infinity.new).must_equal "'-infinity'"
|
106
106
|
end
|
107
107
|
|
108
|
+
it "should raise errors for literalizing random Objects" do
|
109
|
+
proc{@db.literal(Object.new)}.must_raise Sequel::Error
|
110
|
+
end
|
111
|
+
|
108
112
|
it "should format BC dates" do
|
109
113
|
@db.literal(Date.new(-1091, 10, 20)).must_equal "'1092-10-20 BC'"
|
110
114
|
@db.literal(Date.new(1092, 10, 20)).must_equal "'1092-10-20'"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
describe "pg_timestamptz extension" do
|
4
|
+
before do
|
5
|
+
@db = Sequel.mock(:host=>'postgres').extension :pg_timestamptz
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should use timestamptz as default timestamp type" do
|
9
|
+
@db.create_table(:t){Time :t; DateTime :tz; Time :ot, :only_time=>true}
|
10
|
+
@db.sqls.must_equal ['CREATE TABLE "t" ("t" timestamptz, "tz" timestamptz, "ot" time)']
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should use timestamptz when casting" do
|
14
|
+
@db.get(Sequel.cast('a', Time))
|
15
|
+
@db.sqls.must_equal ["SELECT CAST('a' AS timestamptz) AS \"v\" LIMIT 1"]
|
16
|
+
end
|
17
|
+
end
|
@@ -172,6 +172,13 @@ describe "Sequel::Plugins::XmlSerializer" do
|
|
172
172
|
x.first.albums.must_equal [a]
|
173
173
|
end
|
174
174
|
|
175
|
+
it "should work correctly for eager graphed datasets" do
|
176
|
+
ds = Album.dataset.eager_graph(:artist).with_fetch(:id=>1, :name=>'RF', :artist_id=>2, :artist_id_0=>2, :artist_name=>'YJM')
|
177
|
+
albums = Album.array_from_xml(ds.to_xml(:only=>:name, :include=>{:artist=>{:only=>:name}}), :associations=>:artist)
|
178
|
+
albums.must_equal [Album.load(:name=>@album.name)]
|
179
|
+
albums.first.artist.must_equal Artist.load(:name=>@artist.name)
|
180
|
+
end
|
181
|
+
|
175
182
|
it "should raise an error if the dataset does not have a row_proc" do
|
176
183
|
proc{Album.dataset.naked.to_xml}.must_raise(Sequel::Error)
|
177
184
|
end
|
@@ -1217,6 +1217,7 @@ describe "Sequel::Dataset convenience methods" do
|
|
1217
1217
|
@ds.as_hash([:a, :c], :b).must_equal([1, 3]=>2, [5, 7]=>6)
|
1218
1218
|
@ds.as_hash(:a, [:b, :c]).must_equal(1=>[2, 3], 5=>[6, 7])
|
1219
1219
|
@ds.as_hash([:a, :c], [:b, :d]).must_equal([1, 3]=>[2, 4], [5, 7]=>[6, 8])
|
1220
|
+
@ds.extension(:null_dataset).nullify.as_hash([:a, :c], [:b, :d]).must_equal({})
|
1220
1221
|
|
1221
1222
|
@ds.as_hash(:a, :b, :hash => (tmp = {})).must_be_same_as(tmp)
|
1222
1223
|
end
|
@@ -1232,6 +1233,7 @@ describe "Sequel::Dataset convenience methods" do
|
|
1232
1233
|
ds.to_hash_groups([:a, :c], :d).must_equal([1, 3]=>[4, 9], [5, 7]=>[8])
|
1233
1234
|
ds.to_hash_groups(:a, [:b, :d]).must_equal(1=>[[2, 4], [2, 9]], 5=>[[6, 8]])
|
1234
1235
|
ds.to_hash_groups([:a, :c], [:b, :d]).must_equal([1, 3]=>[[2, 4], [2, 9]], [5, 7]=>[[6, 8]])
|
1236
|
+
@ds.extension(:null_dataset).nullify.to_hash_groups([:a, :c], [:b, :d]).must_equal({})
|
1235
1237
|
|
1236
1238
|
ds.to_hash_groups(:a, :d, :hash => (tmp = {})).must_be_same_as(tmp)
|
1237
1239
|
end
|
@@ -1241,6 +1243,7 @@ describe "Sequel::Dataset convenience methods" do
|
|
1241
1243
|
@ds.select_map(:b).must_equal [2, 6]
|
1242
1244
|
@ds.select_map([:a]).must_equal [[1], [5]]
|
1243
1245
|
@ds.select_map([:a, :b]).must_equal [[1, 2], [5, 6]]
|
1246
|
+
@ds.extension(:null_dataset).nullify.select_map([:a, :b]).must_equal []
|
1244
1247
|
|
1245
1248
|
@ds.select_map(Sequel[:a].as(:e)).must_equal [1, 5]
|
1246
1249
|
@ds.select_map(Sequel[:b].as(:e)).must_equal [2, 6]
|
@@ -1258,6 +1261,7 @@ describe "Sequel::Dataset convenience methods" do
|
|
1258
1261
|
@ds.select_order_map(Sequel.qualify(:a, :b).as(:e)).must_equal [2, 6]
|
1259
1262
|
@ds.select_order_map([:a]).must_equal [[1], [5]]
|
1260
1263
|
@ds.select_order_map([Sequel.desc(:a), :b]).must_equal [[5, 6], [1, 2]]
|
1264
|
+
@ds.extension(:null_dataset).nullify.select_order_map(:a).must_equal []
|
1261
1265
|
|
1262
1266
|
@ds.select_order_map(Sequel[:a].as(:e)).must_equal [1, 5]
|
1263
1267
|
@ds.select_order_map(Sequel[:b].as(:e)).must_equal [2, 6]
|
@@ -1278,6 +1282,7 @@ describe "Sequel::Dataset convenience methods" do
|
|
1278
1282
|
@ds.select_hash(:a, [:b, :c]).must_equal(1=>[2, 3], 5=>[6, 7])
|
1279
1283
|
@ds.select_hash([:a, :c], [:b, :d]).must_equal([1, 3]=>[2, 4], [5, 7]=>[6, 8])
|
1280
1284
|
@ds.select_hash(:a, :b, :hash => (tmp = {})).must_be_same_as(tmp)
|
1285
|
+
@ds.extension(:null_dataset).nullify.select_hash(:a, :b).must_equal({})
|
1281
1286
|
end
|
1282
1287
|
|
1283
1288
|
it "should have working #select_hash_groups" do
|
@@ -1292,6 +1297,7 @@ describe "Sequel::Dataset convenience methods" do
|
|
1292
1297
|
ds.select_hash_groups(:a, [:b, :d]).must_equal(1=>[[2, 4], [2, 9]], 5=>[[6, 8]])
|
1293
1298
|
ds.select_hash_groups([:a, :c], [:b, :d]).must_equal([1, 3]=>[[2, 4], [2, 9]], [5, 7]=>[[6, 8]])
|
1294
1299
|
ds.select_hash_groups(:a, :d, :hash => (tmp = {})).must_be_same_as(tmp)
|
1300
|
+
@ds.extension(:null_dataset).nullify.select_hash_groups(:a, :d).must_equal({})
|
1295
1301
|
end
|
1296
1302
|
end
|
1297
1303
|
|
@@ -319,7 +319,7 @@ describe "Bound Argument Types" do
|
|
319
319
|
TrueClass :b
|
320
320
|
end
|
321
321
|
@ds = @db[:items]
|
322
|
-
@vs = {:d=>Date.civil(2010, 10, 11), :dt=>DateTime.civil(2010, 10, 12, 13, 14, 15), :f=>1.0, :s=>'str', :t=>Time.at(
|
322
|
+
@vs = {:d=>Date.civil(2010, 10, 11), :dt=>DateTime.civil(2010, 10, 12, 13, 14, 15), :f=>1.0, :s=>'str', :t=>Time.at(Time.now.to_i), :file=>Sequel::SQL::Blob.new('blob'), :b=>true}
|
323
323
|
end
|
324
324
|
before do
|
325
325
|
@ds.delete
|
@@ -189,23 +189,25 @@ describe "Database index parsing" do
|
|
189
189
|
end
|
190
190
|
|
191
191
|
it "should parse indexes into a hash" do
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
192
|
+
[:items, Sequel.identifier(:items)].each do |table|
|
193
|
+
# Delete :deferrable entry, since not all adapters implement it
|
194
|
+
f = lambda{h = DB.indexes(table); h.values.each{|h2| h2.delete(:deferrable)}; h}
|
195
|
+
|
196
|
+
DB.create_table!(table){Integer :n; Integer :a}
|
197
|
+
f.call.must_equal({})
|
198
|
+
DB.add_index(table, :n)
|
199
|
+
f.call.must_equal(:items_n_index=>{:columns=>[:n], :unique=>false})
|
200
|
+
DB.drop_index(table, :n)
|
201
|
+
f.call.must_equal({})
|
202
|
+
DB.add_index(table, :n, :unique=>true, :name=>:blah_blah_index)
|
203
|
+
f.call.must_equal(:blah_blah_index=>{:columns=>[:n], :unique=>true})
|
204
|
+
DB.add_index(table, [:n, :a])
|
205
|
+
f.call.must_equal(:blah_blah_index=>{:columns=>[:n], :unique=>true}, :items_n_a_index=>{:columns=>[:n, :a], :unique=>false})
|
206
|
+
DB.drop_index(table, :n, :name=>:blah_blah_index)
|
207
|
+
f.call.must_equal(:items_n_a_index=>{:columns=>[:n, :a], :unique=>false})
|
208
|
+
DB.drop_index(table, [:n, :a])
|
209
|
+
f.call.must_equal({})
|
210
|
+
end
|
209
211
|
end
|
210
212
|
|
211
213
|
it "should not include a primary key index" do
|