sequel 0.4.2 → 0.4.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,17 @@
1
+ === 0.4.2.1 (2007-12-09)
2
+
3
+ * Refactored and fixed Dataset#reverse_order to work with field quoting (thanks Christian).
4
+
5
+ * Fixed problem with field quoting in insert statements.
6
+
7
+ * Changed sequelizer code to silently fail on any error when requiring parsetree and ruby2ruby.
8
+
9
+ * Added Database#create_view, #create_or_replace_view and #drop_view methods. Also implemented Dataset#create_view and #create_or_replace_view convenience methods.
10
+
11
+ * Keep DRY by re-using Model#[]= from method_missing.
12
+
13
+ * Added Model.fetch alias for DB.fetch.set_model(Model)
14
+
1
15
  === 0.4.2 (2007-12-07)
2
16
 
3
17
  * Implemented Model#save_changes.
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ require 'fileutils'
6
6
  include FileUtils
7
7
 
8
8
  NAME = "sequel"
9
- VERS = "0.4.2"
9
+ VERS = "0.4.2.1"
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",
@@ -7,7 +7,6 @@ module Sequel
7
7
  module MSSQL
8
8
  class Database < ODBC::Database
9
9
  set_adapter_scheme :odbc_mssql
10
- # set_adapter_scheme :"odbc-mssql"
11
10
 
12
11
  def dataset(opts = nil)
13
12
  MSSQL::Dataset.new(self, opts)
@@ -59,6 +59,7 @@ module Sequel
59
59
  end
60
60
 
61
61
  class ColumnExpr < Expression
62
+ attr_reader :l, :op, :r
62
63
  def initialize(l, op, r = nil); @l, @op, @r = l, op, r; end
63
64
 
64
65
  def to_s(ds)
@@ -194,6 +194,20 @@ module Sequel
194
194
  false
195
195
  end
196
196
 
197
+ def create_view(name, source)
198
+ source = source.sql if source.is_a?(Dataset)
199
+ execute("CREATE VIEW #{name} AS #{source}")
200
+ end
201
+
202
+ def create_or_replace_view(name, source)
203
+ source = source.sql if source.is_a?(Dataset)
204
+ execute("CREATE OR REPLACE VIEW #{name} AS #{source}")
205
+ end
206
+
207
+ def drop_view(name)
208
+ execute("DROP VIEW #{name}")
209
+ end
210
+
197
211
  SQL_BEGIN = 'BEGIN'.freeze
198
212
  SQL_COMMIT = 'COMMIT'.freeze
199
213
  SQL_ROLLBACK = 'ROLLBACK'.freeze
@@ -304,6 +304,14 @@ module Sequel
304
304
  end
305
305
  nil
306
306
  end
307
+
308
+ def create_view(name)
309
+ @db.create_view(name, self)
310
+ end
311
+
312
+ def create_or_replace_view(name)
313
+ @db.create_or_replace_view(name, self)
314
+ end
307
315
  end
308
316
  end
309
317
  end
@@ -263,7 +263,7 @@ end
263
263
 
264
264
  begin
265
265
  require 'parse_tree'
266
- rescue LoadError
266
+ rescue Exception
267
267
  module Sequel::Dataset::Sequelizer
268
268
  def proc_to_sql(proc)
269
269
  raise SequelError, "You must have the ParseTree gem installed in order to use block filters."
@@ -273,7 +273,7 @@ end
273
273
 
274
274
  begin
275
275
  require 'ruby2ruby'
276
- rescue LoadError
276
+ rescue Exception
277
277
  module Sequel::Dataset::Sequelizer
278
278
  def ext_expr(e)
279
279
  raise SequelError, "You must have the Ruby2Ruby gem installed in order to use this block filter."
@@ -152,28 +152,21 @@ module Sequel
152
152
  order(*invert_order(order.empty? ? @opts[:order] : order))
153
153
  end
154
154
 
155
- DESC_ORDER_REGEXP = /^(.*)\sDESC$/i.freeze
156
-
157
155
  # Inverts the given order by breaking it into a list of column references
158
156
  # and inverting them.
159
157
  #
160
- # dataset.invert_order(['id DESC']) #=> ["id"]
161
- # dataset.invert_order(['category, price DESC']) #=>
162
- # ["category DESC, price"]
158
+ # dataset.invert_order([:id.desc]]) #=> [:id]
159
+ # dataset.invert_order(:category, :price.desc]) #=>
160
+ # [:category.desc, :price]
163
161
  def invert_order(order)
164
162
  new_order = []
165
- order.each do |f|
166
- if f.is_a?(String)
167
- f.split(',').each do |r|
168
- r.strip!
169
- new_order << ((r =~ DESC_ORDER_REGEXP ? $1 : r.to_sym.desc).lit)
170
- end
163
+ order.map do |f|
164
+ if f.is_a?(Sequel::SQL::ColumnExpr) && (f.op == Sequel::SQL::ColumnMethods::DESC)
165
+ f.l
171
166
  else
172
- r = literal(f).strip
173
- new_order << ((r =~ DESC_ORDER_REGEXP ? $1 : r.to_sym.desc).lit)
167
+ f.desc
174
168
  end
175
169
  end
176
- new_order
177
170
  end
178
171
 
179
172
  # Returns a copy of the dataset with the results grouped by the value of
@@ -442,7 +435,7 @@ module Sequel
442
435
  if values.empty?
443
436
  "INSERT INTO #{@opts[:from]} DEFAULT VALUES"
444
437
  elsif values.keys
445
- fl = values.keys
438
+ fl = values.keys.map {|f| literal(f.to_sym)}
446
439
  vl = transform_save(values.values).map {|v| literal(v)}
447
440
  "INSERT INTO #{@opts[:from]} (#{fl.join(COMMA_SEPARATOR)}) VALUES (#{vl.join(COMMA_SEPARATOR)})"
448
441
  else
@@ -454,7 +447,7 @@ module Sequel
454
447
  "INSERT INTO #{@opts[:from]} DEFAULT VALUES"
455
448
  else
456
449
  fl, vl = [], []
457
- values.each {|k, v| fl << k.to_s; vl << literal(v)}
450
+ values.each {|k, v| fl << literal(k.to_sym); vl << literal(v)}
458
451
  "INSERT INTO #{@opts[:from]} (#{fl.join(COMMA_SEPARATOR)}) VALUES (#{vl.join(COMMA_SEPARATOR)})"
459
452
  end
460
453
  when Dataset
data/lib/sequel/model.rb CHANGED
@@ -259,6 +259,10 @@ module Sequel
259
259
  dataset[(Hash === args) ? args : primary_key_hash(args)]
260
260
  end
261
261
 
262
+ def self.fetch(*args)
263
+ db.fetch(*args).set_model(self)
264
+ end
265
+
262
266
  # Like find but invokes create with given conditions when record does not
263
267
  # exists.
264
268
  def self.find_or_create(cond)
@@ -284,12 +284,9 @@ module Sequel
284
284
  # define the column accessor
285
285
  Thread.exclusive do
286
286
  if write
287
- model.class_def(m) do |v|
288
- @values[att] = v
289
- @changed_columns << att unless @changed_columns.include?(att)
290
- end
287
+ model.class_def(m) {|v| self[att] = v}
291
288
  else
292
- model.class_def(m) {@values[att]}
289
+ model.class_def(m) {self[att]}
293
290
  end
294
291
  end
295
292
 
@@ -96,7 +96,7 @@ context "A MySQL dataset" do
96
96
 
97
97
  @d.order(:name.DESC).sql.should == \
98
98
  'SELECT * FROM items ORDER BY `name` DESC'
99
-
99
+
100
100
  @d.select('items.name AS item_name'.lit).sql.should == \
101
101
  'SELECT items.name AS item_name FROM items'
102
102
 
@@ -118,8 +118,22 @@ context "A MySQL dataset" do
118
118
  @d.insert_sql(:value => 333).should == \
119
119
  'INSERT INTO items (`value`) VALUES (333)'
120
120
 
121
- @d.insert_sql(:x => :y).should == \
122
- 'INSERT INTO items (`x`) VALUES (`y`)'
121
+ @d.insert_sql(:x => :y).should == \
122
+ 'INSERT INTO items (`x`) VALUES (`y`)'
123
+ end
124
+
125
+ specify "should quote fields correctly when reversing the order" do
126
+ @d.reverse_order(:name).sql.should == \
127
+ 'SELECT * FROM items ORDER BY `name` DESC'
128
+
129
+ @d.reverse_order(:name.DESC).sql.should == \
130
+ 'SELECT * FROM items ORDER BY `name`'
131
+
132
+ @d.reverse_order(:name, :test.DESC).sql.should == \
133
+ 'SELECT * FROM items ORDER BY `name` DESC, `test`'
134
+
135
+ @d.reverse_order(:name.DESC, :test).sql.should == \
136
+ 'SELECT * FROM items ORDER BY `name`, `test` DESC'
123
137
  end
124
138
 
125
139
  specify "should support ORDER clause in UPDATE statements" do
@@ -600,4 +600,49 @@ context "Database#[]" do
600
600
  @db['select * from xyz where x = ? and y = ?', 15, 'abc'].each {|r| sql = r[:sql]}
601
601
  sql.should == "select * from xyz where x = 15 and y = 'abc'"
602
602
  end
603
- end
603
+ end
604
+
605
+ context "Database#create_view" do
606
+ setup do
607
+ @db = DummyDatabase.new
608
+ end
609
+
610
+ specify "should construct proper SQL with raw SQL" do
611
+ @db.create_view :test, "SELECT * FROM xyz"
612
+ @db.sqls.should == ['CREATE VIEW test AS SELECT * FROM xyz']
613
+ end
614
+
615
+ specify "should construct proper SQL with dataset" do
616
+ @db.create_view :test, @db[:items].select(:a, :b).order(:c)
617
+ @db.sqls.should == ['CREATE VIEW test AS SELECT a, b FROM items ORDER BY c']
618
+ end
619
+ end
620
+
621
+ context "Database#create_or_replace_view" do
622
+ setup do
623
+ @db = DummyDatabase.new
624
+ end
625
+
626
+ specify "should construct proper SQL with raw SQL" do
627
+ @db.create_or_replace_view :test, "SELECT * FROM xyz"
628
+ @db.sqls.should == ['CREATE OR REPLACE VIEW test AS SELECT * FROM xyz']
629
+ end
630
+
631
+ specify "should construct proper SQL with dataset" do
632
+ @db.create_or_replace_view :test, @db[:items].select(:a, :b).order(:c)
633
+ @db.sqls.should == ['CREATE OR REPLACE VIEW test AS SELECT a, b FROM items ORDER BY c']
634
+ end
635
+ end
636
+
637
+ context "Database#drop_view" do
638
+ setup do
639
+ @db = DummyDatabase.new
640
+ end
641
+
642
+ specify "should construct proper SQL" do
643
+ @db.drop_view :test
644
+ @db.sqls.should == ['DROP VIEW test']
645
+ end
646
+ end
647
+
648
+
data/spec/dataset_spec.rb CHANGED
@@ -752,7 +752,7 @@ context "Dataset#reverse_order" do
752
752
  specify "should reverse a previous ordering if no arguments are given" do
753
753
  @dataset.order(:name).reverse_order.sql.should ==
754
754
  'SELECT * FROM test ORDER BY name DESC'
755
- @dataset.order('clumsy DESC, fool').reverse_order.sql.should ==
755
+ @dataset.order(:clumsy.DESC, :fool).reverse_order.sql.should ==
756
756
  'SELECT * FROM test ORDER BY clumsy, fool DESC'
757
757
  end
758
758
  end
@@ -2278,4 +2278,47 @@ context "Dataset magic methods" do
2278
2278
  @ds.last_by_name('sharon').should == {:a => 1, :b => 2}
2279
2279
  @c.sqls.should == ["SELECT * FROM items ORDER BY name DESC LIMIT 1"] * 2
2280
2280
  end
2281
- end
2281
+ end
2282
+
2283
+ context "Dataset#create_view" do
2284
+ setup do
2285
+ @dbc = Class.new(Sequel::Database) do
2286
+ attr_reader :sqls
2287
+
2288
+ def execute(sql)
2289
+ @sqls ||= []
2290
+ @sqls << sql
2291
+ end
2292
+ end
2293
+ @db = @dbc.new
2294
+
2295
+ @ds = @db[:items].order(:abc).filter(:category => 'ruby')
2296
+ end
2297
+
2298
+ specify "should create a view with the dataset's sql" do
2299
+ @ds.create_view(:xyz)
2300
+ @db.sqls.should == ["CREATE VIEW xyz AS #{@ds.sql}"]
2301
+ end
2302
+ end
2303
+
2304
+ context "Dataset#create_or_replace_view" do
2305
+ setup do
2306
+ @dbc = Class.new(Sequel::Database) do
2307
+ attr_reader :sqls
2308
+
2309
+ def execute(sql)
2310
+ @sqls ||= []
2311
+ @sqls << sql
2312
+ end
2313
+ end
2314
+ @db = @dbc.new
2315
+
2316
+ @ds = @db[:items].order(:abc).filter(:category => 'ruby')
2317
+ end
2318
+
2319
+ specify "should create a view with the dataset's sql" do
2320
+ @ds.create_or_replace_view(:xyz)
2321
+ @db.sqls.should == ["CREATE OR REPLACE VIEW xyz AS #{@ds.sql}"]
2322
+ end
2323
+ end
2324
+
data/spec/model_spec.rb CHANGED
@@ -724,6 +724,17 @@ context "Model.[]" do
724
724
  end
725
725
  end
726
726
 
727
+ context "Model.fetch" do
728
+ setup do
729
+ MODEL_DB.reset
730
+ @c = Class.new(Sequel::Model(:items))
731
+ end
732
+
733
+ specify "should return instances of Model" do
734
+ @c.fetch("SELECT * FROM items").first.should be_a_kind_of(@c)
735
+ end
736
+ end
737
+
727
738
  context "A cached model" do
728
739
  setup do
729
740
  MODEL_DB.reset
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2007-12-07 00:00:00 +02:00
12
+ date: 2007-12-09 00:00:00 +02:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency