sequel 0.2.0.1 → 0.2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +22 -0
- data/Rakefile +1 -1
- data/lib/sequel/core_ext.rb +1 -1
- data/lib/sequel/dataset/sequelizer.rb +6 -6
- data/lib/sequel/dataset/sql.rb +19 -13
- data/lib/sequel/migration.rb +2 -0
- data/lib/sequel/model.rb +3 -2
- data/lib/sequel/mysql.rb +5 -0
- data/lib/sequel/pretty_table.rb +9 -1
- data/spec/dataset_spec.rb +20 -8
- data/spec/migration_spec.rb +9 -1
- data/spec/model_spec.rb +11 -0
- data/spec/pretty_table_spec.rb +2 -2
- data/spec/sequelizer_spec.rb +11 -2
- metadata +2 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
=== 0.2.0.2 (2007-09-07)
|
2
|
+
|
3
|
+
* Dataset#insert can now accept subqueries.
|
4
|
+
|
5
|
+
* Changed Migrator.apply to return the version.
|
6
|
+
|
7
|
+
* Changed Sequel::Model() to cache intermediate classes so descendant classes can be reopened (#39).
|
8
|
+
|
9
|
+
* Added :charset option to MySQL adapter (#40).
|
10
|
+
|
11
|
+
* Fixed Dataset#exclude to add parens around NOT expression (#38).
|
12
|
+
|
13
|
+
* Fixed use of sub-queries with all comparison operators in block filters (#38).
|
14
|
+
|
15
|
+
* Fixed arithmetic expressions in block filters to not be literalized.
|
16
|
+
|
17
|
+
* Changed Symbol#method_missing to return LiteralString.
|
18
|
+
|
19
|
+
* Changed PrettyTable to right-align numbers.
|
20
|
+
|
21
|
+
* Fixed Model.create_table (thanks Duane Johnson.)
|
22
|
+
|
1
23
|
=== 0.2.0.1 (2007-09-04)
|
2
24
|
|
3
25
|
* Improved support for invoking methods with inline procs inside block filters.
|
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ require 'fileutils'
|
|
6
6
|
include FileUtils
|
7
7
|
|
8
8
|
NAME = "sequel"
|
9
|
-
VERS = "0.2.0.
|
9
|
+
VERS = "0.2.0.2"
|
10
10
|
CLEAN.include ['**/.*.sw?', 'pkg/*', '.config', 'doc/*', 'coverage/*']
|
11
11
|
RDOC_OPTS = ['--quiet', '--title', "Sequel: Concise ORM for Ruby",
|
12
12
|
"--opname", "index.html",
|
data/lib/sequel/core_ext.rb
CHANGED
@@ -134,7 +134,7 @@ class Symbol
|
|
134
134
|
# method name is made of all upper case letters.
|
135
135
|
def method_missing(sym)
|
136
136
|
((s = sym.to_s) =~ /^([A-Z]+)$/) ? \
|
137
|
-
"#{s.downcase}(#{to_field_name})" : super
|
137
|
+
"#{s.downcase}(#{to_field_name})".lit : super
|
138
138
|
end
|
139
139
|
|
140
140
|
# Formats an SQL function with optional parameters
|
@@ -106,9 +106,9 @@ class Sequel::Dataset
|
|
106
106
|
def call_expr(e, b)
|
107
107
|
case op = e[2]
|
108
108
|
when :>, :<, :>=, :<=
|
109
|
-
l =
|
110
|
-
r =
|
111
|
-
"(#{l} #{op} #{r})"
|
109
|
+
l = eval_expr(e[1], b)
|
110
|
+
r = eval_expr(e[3][1], b)
|
111
|
+
"(#{literal(l)} #{op} #{literal(r)})"
|
112
112
|
when :==
|
113
113
|
l = eval_expr(e[1], b)
|
114
114
|
r = eval_expr(e[3][1], b)
|
@@ -118,9 +118,9 @@ class Sequel::Dataset
|
|
118
118
|
r = eval_expr(e[3][1], b)
|
119
119
|
match_expr(l, r)
|
120
120
|
when :+, :-, :*, :/, :%
|
121
|
-
l =
|
122
|
-
r =
|
123
|
-
"(#{l} #{op} #{r})"
|
121
|
+
l = eval_expr(e[1], b)
|
122
|
+
r = eval_expr(e[3][1], b)
|
123
|
+
"(#{literal(l)} #{op} #{literal(r)})".lit
|
124
124
|
when :in, :in?
|
125
125
|
# in/in? operators are supported using two forms:
|
126
126
|
# :x.in([1, 2, 3])
|
data/lib/sequel/dataset/sql.rb
CHANGED
@@ -249,9 +249,9 @@ module Sequel
|
|
249
249
|
if @opts[clause]
|
250
250
|
l = expression_list(@opts[clause])
|
251
251
|
r = expression_list(block || cond, parenthesize)
|
252
|
-
cond = "#{l} AND NOT #{r}"
|
252
|
+
cond = "#{l} AND (NOT #{r})"
|
253
253
|
else
|
254
|
-
cond = "NOT #{expression_list(block || cond, true)}"
|
254
|
+
cond = "(NOT #{expression_list(block || cond, true)})"
|
255
255
|
end
|
256
256
|
clone_merge(clause => cond)
|
257
257
|
end
|
@@ -420,18 +420,24 @@ module Sequel
|
|
420
420
|
def insert_sql(*values)
|
421
421
|
if values.empty?
|
422
422
|
"INSERT INTO #{@opts[:from]} DEFAULT VALUES;"
|
423
|
-
elsif (values.size == 1) && values[0].is_a?(Hash)
|
424
|
-
field_list = []
|
425
|
-
value_list = []
|
426
|
-
values[0].each do |k, v|
|
427
|
-
field_list << field_name(k)
|
428
|
-
value_list << literal(v)
|
429
|
-
end
|
430
|
-
fl = field_list.join(COMMA_SEPARATOR)
|
431
|
-
vl = value_list.join(COMMA_SEPARATOR)
|
432
|
-
"INSERT INTO #{@opts[:from]} (#{fl}) VALUES (#{vl});"
|
433
423
|
else
|
434
|
-
|
424
|
+
values = values[0] if values.size == 1
|
425
|
+
case values
|
426
|
+
when Hash
|
427
|
+
field_list = []
|
428
|
+
value_list = []
|
429
|
+
values.each do |k, v|
|
430
|
+
field_list << field_name(k)
|
431
|
+
value_list << literal(v)
|
432
|
+
end
|
433
|
+
fl = field_list.join(COMMA_SEPARATOR)
|
434
|
+
vl = value_list.join(COMMA_SEPARATOR)
|
435
|
+
"INSERT INTO #{@opts[:from]} (#{fl}) VALUES (#{vl});"
|
436
|
+
when Dataset
|
437
|
+
"INSERT INTO #{@opts[:from]} #{literal(values)}"
|
438
|
+
else
|
439
|
+
"INSERT INTO #{@opts[:from]} VALUES (#{literal(values)});"
|
440
|
+
end
|
435
441
|
end
|
436
442
|
end
|
437
443
|
|
data/lib/sequel/migration.rb
CHANGED
data/lib/sequel/model.rb
CHANGED
@@ -78,7 +78,7 @@ module Sequel
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def self.create_table
|
81
|
-
db.
|
81
|
+
db.create_table_sql_list(*schema.create_info).each {|s| db << s}
|
82
82
|
end
|
83
83
|
|
84
84
|
def self.drop_table
|
@@ -292,7 +292,8 @@ module Sequel
|
|
292
292
|
end
|
293
293
|
|
294
294
|
def self.Model(table)
|
295
|
-
|
295
|
+
@models ||= {}
|
296
|
+
@models[table] ||= Class.new(Sequel::Model) do
|
296
297
|
meta_def(:inherited) do |c|
|
297
298
|
if table.is_a?(Dataset)
|
298
299
|
c.set_dataset(table)
|
data/lib/sequel/mysql.rb
CHANGED
@@ -69,6 +69,11 @@ module Sequel
|
|
69
69
|
conn = Mysql.real_connect(@opts[:host], @opts[:user], @opts[:password],
|
70
70
|
@opts[:database], @opts[:port])
|
71
71
|
conn.query_with_result = false
|
72
|
+
if @opts[:charset]
|
73
|
+
conn.query("set character_set_connection = '#{@opts[:charset]}';")
|
74
|
+
conn.query("set character_set_client = '#{@opts[:charset]}';")
|
75
|
+
conn.query("set character_set_results = '#{@opts[:charset]}';")
|
76
|
+
end
|
72
77
|
conn.reconnect = true
|
73
78
|
conn
|
74
79
|
end
|
data/lib/sequel/pretty_table.rb
CHANGED
@@ -36,8 +36,16 @@ module Sequel
|
|
36
36
|
'+' + columns.map {|c| '-' * sizes[c]}.join('+') + '+'
|
37
37
|
end
|
38
38
|
|
39
|
+
def self.format_cell(size, v)
|
40
|
+
case v
|
41
|
+
when Bignum, Fixnum: "%#{size}d" % v
|
42
|
+
when Float: "%#{size}g" % v
|
43
|
+
else "%-#{size}s" % v.to_s
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
39
47
|
def self.data_line(columns, sizes, record)
|
40
|
-
'|' + columns.map {|c|
|
48
|
+
'|' + columns.map {|c| format_cell(sizes[c], record[c])}.join('|') + '|'
|
41
49
|
end
|
42
50
|
|
43
51
|
def self.header_line(columns, sizes)
|
data/spec/dataset_spec.rb
CHANGED
@@ -98,10 +98,22 @@ context "A simple dataset" do
|
|
98
98
|
@dataset.delete_sql.should == 'DELETE FROM test'
|
99
99
|
end
|
100
100
|
|
101
|
-
specify "should format an insert statement" do
|
101
|
+
specify "should format an insert statement with default values" do
|
102
102
|
@dataset.insert_sql.should == 'INSERT INTO test DEFAULT VALUES;'
|
103
|
+
end
|
104
|
+
|
105
|
+
specify "should format an insert statement with hash" do
|
103
106
|
@dataset.insert_sql(:name => 'wxyz', :price => 342).
|
104
107
|
should match(/INSERT INTO test \(name, price\) VALUES \('wxyz', 342\)|INSERT INTO test \(price, name\) VALUES \(342, 'wxyz'\)/)
|
108
|
+
end
|
109
|
+
|
110
|
+
specify "should format an insert statement with sub-query" do
|
111
|
+
@sub = Sequel::Dataset.new(nil).from(:something).filter(:x => 2)
|
112
|
+
@dataset.insert_sql(@sub).should == \
|
113
|
+
"INSERT INTO test (SELECT * FROM something WHERE (x = 2))"
|
114
|
+
end
|
115
|
+
|
116
|
+
specify "should format an insert statement with array" do
|
105
117
|
@dataset.insert_sql('a', 2, 6.5).should ==
|
106
118
|
"INSERT INTO test VALUES ('a', 2, 6.5);"
|
107
119
|
end
|
@@ -361,33 +373,33 @@ context "Dataset#exclude" do
|
|
361
373
|
|
362
374
|
specify "should correctly include the NOT operator when one condition is given" do
|
363
375
|
@dataset.exclude(:region=>'Asia').select_sql.should ==
|
364
|
-
"SELECT * FROM test WHERE NOT (region = 'Asia')"
|
376
|
+
"SELECT * FROM test WHERE (NOT (region = 'Asia'))"
|
365
377
|
end
|
366
378
|
|
367
379
|
specify "should take multiple conditions as a hash and express the logic correctly in SQL" do
|
368
380
|
@dataset.exclude(:region => 'Asia', :name => 'Japan').select_sql.
|
369
|
-
should match(Regexp.union(/WHERE NOT \(\(region = 'Asia'\) AND \(name = 'Japan'\)\)/,
|
370
|
-
/WHERE NOT \(\(name = 'Japan'\) AND \(region = 'Asia'\)\)/))
|
381
|
+
should match(Regexp.union(/WHERE \(NOT \(\(region = 'Asia'\) AND \(name = 'Japan'\)\)\)/,
|
382
|
+
/WHERE \(NOT \(\(name = 'Japan'\) AND \(region = 'Asia'\)\)\)/))
|
371
383
|
end
|
372
384
|
|
373
385
|
specify "should parenthesize a single string condition correctly" do
|
374
386
|
@dataset.exclude("region = 'Asia' AND name = 'Japan'").select_sql.should ==
|
375
|
-
"SELECT * FROM test WHERE NOT (region = 'Asia' AND name = 'Japan')"
|
387
|
+
"SELECT * FROM test WHERE (NOT (region = 'Asia' AND name = 'Japan'))"
|
376
388
|
end
|
377
389
|
|
378
390
|
specify "should parenthesize an array condition correctly" do
|
379
391
|
@dataset.exclude('region = ? AND name = ?', 'Asia', 'Japan').select_sql.should ==
|
380
|
-
"SELECT * FROM test WHERE NOT (region = 'Asia' AND name = 'Japan')"
|
392
|
+
"SELECT * FROM test WHERE (NOT (region = 'Asia' AND name = 'Japan'))"
|
381
393
|
end
|
382
394
|
|
383
395
|
specify "should corrently parenthesize when it is used twice" do
|
384
396
|
@dataset.exclude(:region => 'Asia').exclude(:name => 'Japan').select_sql.should ==
|
385
|
-
"SELECT * FROM test WHERE NOT (region = 'Asia') AND NOT (name = 'Japan')"
|
397
|
+
"SELECT * FROM test WHERE (NOT (region = 'Asia')) AND (NOT (name = 'Japan'))"
|
386
398
|
end
|
387
399
|
|
388
400
|
specify "should support proc expressions" do
|
389
401
|
@dataset.exclude {:id == (6...12)}.sql.should ==
|
390
|
-
'SELECT * FROM test WHERE NOT ((id >= 6 AND id < 12))'
|
402
|
+
'SELECT * FROM test WHERE (NOT ((id >= 6 AND id < 12)))'
|
391
403
|
end
|
392
404
|
end
|
393
405
|
|
data/spec/migration_spec.rb
CHANGED
@@ -229,7 +229,7 @@ context "Sequel::Migrator" do
|
|
229
229
|
|
230
230
|
Sequel::Migrator.get_current_migration_version(@db).should == 5
|
231
231
|
end
|
232
|
-
|
232
|
+
|
233
233
|
specify "should apply migrations correctly in the down direction" do
|
234
234
|
Sequel::Migrator.apply(@db, '.', 1, 5)
|
235
235
|
@db.drops.should == [5555, 3333, 2222]
|
@@ -250,4 +250,12 @@ context "Sequel::Migrator" do
|
|
250
250
|
|
251
251
|
Sequel::Migrator.get_current_migration_version(@db).should == 0
|
252
252
|
end
|
253
|
+
|
254
|
+
specify "should return the target version" do
|
255
|
+
Sequel::Migrator.apply(@db, '.', 3, 2).should == 3
|
256
|
+
|
257
|
+
Sequel::Migrator.apply(@db, '.', 0).should == 0
|
258
|
+
|
259
|
+
Sequel::Migrator.apply(@db, '.').should == 5
|
260
|
+
end
|
253
261
|
end
|
data/spec/model_spec.rb
CHANGED
@@ -44,4 +44,15 @@ describe Sequel::Model do
|
|
44
44
|
it "puts the lotion in the basket or it gets the hose again" do
|
45
45
|
# just kidding!
|
46
46
|
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class DummyModelBased < Sequel::Model(:blog)
|
50
|
+
end
|
51
|
+
|
52
|
+
context "Sequel::Model()" do
|
53
|
+
specify "should allow reopening of descendant classes" do
|
54
|
+
proc do
|
55
|
+
eval "class DummyModelBased < Sequel::Model(:blog); end"
|
56
|
+
end.should_not raise_error
|
57
|
+
end
|
47
58
|
end
|
data/spec/pretty_table_spec.rb
CHANGED
@@ -39,14 +39,14 @@ context "PrettyTable" do
|
|
39
39
|
Sequel::PrettyTable.print(@data2, [:a, :b])
|
40
40
|
@output.rewind
|
41
41
|
@output.read.should == \
|
42
|
-
"+--+----+\n|a |b |\n+--+----+\n|23|45
|
42
|
+
"+--+----+\n|a |b |\n+--+----+\n|23| 45|\n|45|2377|\n+--+----+\n"
|
43
43
|
end
|
44
44
|
|
45
45
|
specify "should also take header width into account" do
|
46
46
|
Sequel::PrettyTable.print(@data3, [:aaa, :bb, :c])
|
47
47
|
@output.rewind
|
48
48
|
@output.read.should == \
|
49
|
-
"+---+--+-+\n|aaa|bb|c|\n+---+--+-+\n|1
|
49
|
+
"+---+--+-+\n|aaa|bb|c|\n+---+--+-+\n| 1| | |\n| | 2| |\n| | |3|\n+---+--+-+\n"
|
50
50
|
end
|
51
51
|
|
52
52
|
specify "should print only the specified columns" do
|
data/spec/sequelizer_spec.rb
CHANGED
@@ -175,6 +175,12 @@ context "Proc#to_sql" do
|
|
175
175
|
|
176
176
|
proc {:x == (a...b)}.to_sql.should == \
|
177
177
|
"(x >= 3 AND x < 5)"
|
178
|
+
|
179
|
+
t1 = Time.now - 4000
|
180
|
+
t2 = Time.now - 2000
|
181
|
+
|
182
|
+
proc {:stamp == (t1..t2)}.to_sql.should == \
|
183
|
+
"(stamp >= #{DS.literal(t1)} AND stamp <= #{DS.literal(t2)})"
|
178
184
|
end
|
179
185
|
|
180
186
|
specify "should support comparison to sub-queries" do
|
@@ -186,8 +192,11 @@ context "Proc#to_sql" do
|
|
186
192
|
# proc {:id == DB[:test].select(:node_id)}.to_sql.should == \
|
187
193
|
# "(id IN (SELECT node_id FROM test))"
|
188
194
|
|
189
|
-
proc {:id == DB[:test].select(:node_id).filter {:active == true}}.to_sql.should == \
|
190
|
-
"(id IN (SELECT node_id FROM test WHERE (active = 't')))"
|
195
|
+
# proc {:id == DB[:test].select(:node_id).filter {:active == true}}.to_sql.should == \
|
196
|
+
# "(id IN (SELECT node_id FROM test WHERE (active = 't')))"
|
197
|
+
|
198
|
+
proc {:price >= DB[:items].select(:price)}.to_sql.should == \
|
199
|
+
"(price >= (SELECT price FROM items))"
|
191
200
|
end
|
192
201
|
|
193
202
|
specify "should support comparison to arrays" do
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: sequel
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.2.0.
|
7
|
-
date: 2007-09-
|
6
|
+
version: 0.2.0.2
|
7
|
+
date: 2007-09-07 00:00:00 +03:00
|
8
8
|
summary: Lightweight ORM library for Ruby
|
9
9
|
require_paths:
|
10
10
|
- lib
|