sequel 0.4.2 → 0.4.2.1

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.
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