sequel 0.0.18 → 0.0.19

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,21 @@
1
+ *0.0.19*
2
+
3
+ * More specs for Dataset.
4
+
5
+ * Fixed Dataset#invert_order to work correctly with strings.
6
+
7
+ * Fixed Model#== to check equality of values.
8
+
9
+ * Added Model#exclude and Model#order.
10
+
11
+ * Fixed Dataset#order and Dataset#group to behave correctly when supplied with qualified field name symbols.
12
+
13
+ * Removed Database#literal. Shouldn't have been there.
14
+
15
+ * Added SQLite::Dataset#explain. Returns an array of opcode hashes.
16
+
17
+ * Specs for ConnectionPool.
18
+
1
19
  *0.0.18*
2
20
 
3
21
  * Implemented SequelError and SequelConnectionError classes. ConnectionPool#hold now catches any connection errors and reraises them SequelConnectionError.
data/README CHANGED
@@ -9,6 +9,7 @@ Sequel makes it easy to deal with multiple records without having to break your
9
9
  * {Project page}[http://code.google.com/p/ruby-sequel/]
10
10
  * {Source code}[http://ruby-sequel.googlecode.com/svn/]
11
11
  * {Bug tracking}[http://code.google.com/p/ruby-sequel/issues/list]
12
+ * {Google group}[http://groups.google.com/group/sequel-talk]
12
13
  * {RubyForge page}[http://rubyforge.org/projects/sequel/]
13
14
 
14
15
  To check out the source code:
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ require 'fileutils'
6
6
  include FileUtils
7
7
 
8
8
  NAME = "sequel"
9
- VERS = "0.0.18"
9
+ VERS = "0.0.19"
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",
@@ -43,7 +43,9 @@ module Sequel
43
43
 
44
44
  def acquire(thread)
45
45
  @mutex.synchronize do
46
- @allocated[thread] = available
46
+ if conn = available
47
+ @allocated[thread] = conn
48
+ end
47
49
  end
48
50
  end
49
51
 
@@ -34,13 +34,15 @@ module Sequel
34
34
  alias_method :[], :from
35
35
 
36
36
  def execute(sql)
37
- raise RuntimeError
37
+ raise NotImplementedError
38
38
  end
39
39
 
40
+ # Acquires a database connection, yielding it to the passed block.
40
41
  def synchronize(&block)
41
42
  @pool.hold(&block)
42
43
  end
43
-
44
+
45
+ # Returns true if there is a database connection
44
46
  def test_connection
45
47
  @pool.hold {|conn|} if @pool
46
48
  true
@@ -55,15 +57,6 @@ module Sequel
55
57
  execute(sql)
56
58
  end
57
59
 
58
- # Returns a literal SQL representation of a value. This method is usually
59
- # overriden in database adapters.
60
- def literal(v)
61
- case v
62
- when String: "'%s'" % v
63
- else v.to_s
64
- end
65
- end
66
-
67
60
  # Creates a table. The easiest way to use this method is to provide a
68
61
  # block:
69
62
  # DB.create_table :posts do
@@ -104,23 +97,24 @@ module Sequel
104
97
  SQL_BEGIN = 'BEGIN'.freeze
105
98
  SQL_COMMIT = 'COMMIT'.freeze
106
99
  SQL_ROLLBACK = 'ROLLBACK'.freeze
107
-
100
+
101
+ # A simple implementation of SQL transactions. Nested transactions are not
102
+ # supported - calling #transaction within a transaction will reuse the
103
+ # current transaction. May be overridden for databases that support nested
104
+ # transactions.
108
105
  def transaction
109
106
  @pool.hold do |conn|
110
107
  @transactions ||= []
111
108
  if @transactions.include? Thread.current
112
109
  return yield(conn)
113
110
  end
114
- # ServerSide.info('BEGIN')
115
111
  conn.execute(SQL_BEGIN)
116
112
  begin
117
113
  @transactions << Thread.current
118
114
  result = yield(conn)
119
- # ServerSide.info('COMMIT')
120
115
  conn.execute(SQL_COMMIT)
121
116
  result
122
117
  rescue => e
123
- # ServerSide.info('ROLLBACK')
124
118
  conn.execute(SQL_ROLLBACK)
125
119
  raise e
126
120
  ensure
@@ -132,11 +126,14 @@ module Sequel
132
126
  @@adapters = Hash.new
133
127
 
134
128
  # Sets the adapter scheme for the database class. Call this method in
135
- # descendnants of Database to allow connection using a URL. For example:
129
+ # descendnants of Database to allow connection using a URL. For example the
130
+ # following:
136
131
  # class DB2::Database < Sequel::Database
137
132
  # set_adapter_scheme :db2
138
133
  # ...
139
134
  # end
135
+ # would allow connection using:
136
+ # Sequel.open('db2://user:password@dbserver/mydb')
140
137
  def self.set_adapter_scheme(scheme)
141
138
  @@adapters[scheme.to_sym] = self
142
139
  end
@@ -51,7 +51,7 @@ module Sequel
51
51
  # objects). If no record class is defined for the dataset, self is
52
52
  # returned.
53
53
  def naked
54
- @record_class ? self.class.new(@db, @opts) : self
54
+ @record_class ? self.class.new(@db, @opts.dup) : self
55
55
  end
56
56
 
57
57
  AS_REGEXP = /(.*)___(.*)/.freeze
@@ -90,7 +90,7 @@ module Sequel
90
90
 
91
91
  # Converts an array of sources into a comma separated list.
92
92
  def source_list(source)
93
- raise 'No source specified for query' unless source
93
+ raise SequelError, 'No source specified for query' unless source
94
94
  source.map {|i| i.is_a?(Dataset) ? i.to_table_reference : i}.
95
95
  join(COMMA_SEPARATOR)
96
96
  end
@@ -109,7 +109,7 @@ module Sequel
109
109
  when Array: v.empty? ? NULL : v.map {|i| literal(i)}.join(COMMA_SEPARATOR)
110
110
  when Dataset: SUBQUERY % v.sql
111
111
  else
112
- raise "can't express #{v.inspect}:#{v.class} as a SQL literal"
112
+ raise SequelError, "can't express #{v.inspect}:#{v.class} as a SQL literal"
113
113
  end
114
114
  end
115
115
 
@@ -195,9 +195,14 @@ module Sequel
195
195
  DESC_ORDER_REGEXP = /(.*)\sDESC/.freeze
196
196
 
197
197
  def invert_order(order)
198
- order.map do |f|
199
- f.to_s =~ DESC_ORDER_REGEXP ? $1 : f.DESC
198
+ new_order = []
199
+ order.each do |f|
200
+ f.to_s.split(',').map do |p|
201
+ p.strip!
202
+ new_order << (p =~ DESC_ORDER_REGEXP ? $1 : p.to_sym.DESC)
203
+ end
200
204
  end
205
+ new_order
201
206
  end
202
207
 
203
208
  # Returns a copy of the dataset with the results grouped by the value of
@@ -240,7 +245,7 @@ module Sequel
240
245
  # if the dataset has been grouped. See also #filter
241
246
  def where(*cond)
242
247
  if @opts[:group]
243
- raise "Can't specify a WHERE clause once the dataset has been grouped"
248
+ raise SequelError, "Can't specify a WHERE clause once the dataset has been grouped"
244
249
  else
245
250
  filter(*cond)
246
251
  end
@@ -250,7 +255,7 @@ module Sequel
250
255
  # if the dataset has not been grouped. See also #filter
251
256
  def having(*cond)
252
257
  unless @opts[:group]
253
- raise "Can only specify a HAVING clause on a grouped dataset"
258
+ raise SequelError, "Can only specify a HAVING clause on a grouped dataset"
254
259
  else
255
260
  filter(*cond)
256
261
  end
@@ -331,11 +336,11 @@ module Sequel
331
336
  end
332
337
 
333
338
  if group = opts[:group]
334
- sql << (GROUP % group.join(COMMA_SEPARATOR))
339
+ sql << (GROUP % field_list(group))
335
340
  end
336
341
 
337
342
  if order = opts[:order]
338
- sql << (ORDER % order.join(COMMA_SEPARATOR))
343
+ sql << (ORDER % field_list(order))
339
344
  end
340
345
 
341
346
  if having = opts[:having]
@@ -384,9 +389,9 @@ module Sequel
384
389
  opts = opts ? @opts.merge(opts) : @opts
385
390
 
386
391
  if opts[:group]
387
- raise "Can't update a grouped dataset"
392
+ raise SequelError, "Can't update a grouped dataset"
388
393
  elsif (opts[:from].size > 1) or opts[:join_type]
389
- raise "Can't update a joined dataset"
394
+ raise SequelError, "Can't update a joined dataset"
390
395
  end
391
396
 
392
397
  set_list = values.map {|kv| SET_FORMAT % [kv[0], literal(kv[1])]}.
@@ -406,9 +411,9 @@ module Sequel
406
411
  opts = opts ? @opts.merge(opts) : @opts
407
412
 
408
413
  if opts[:group]
409
- raise "Can't delete from a grouped dataset"
414
+ raise SequelError, "Can't delete from a grouped dataset"
410
415
  elsif opts[:from].is_a?(Array) && opts[:from].size > 1
411
- raise "Can't delete from a joined dataset"
416
+ raise SequelError, "Can't delete from a joined dataset"
412
417
  end
413
418
 
414
419
  sql = DELETE % opts[:from]
@@ -495,7 +500,8 @@ module Sequel
495
500
  end
496
501
 
497
502
  def last(num = 1)
498
- raise 'No order specified' unless @opts[:order] || (opts && opts[:order])
503
+ raise SequelError, 'No order specified' unless
504
+ @opts[:order] || (opts && opts[:order])
499
505
 
500
506
  l = {:limit => num}
501
507
  opts = {:order => invert_order(@opts[:order])}.
@@ -511,7 +517,7 @@ module Sequel
511
517
  # Deletes all records in the dataset one at a time by invoking the destroy
512
518
  # method of the associated model class.
513
519
  def destroy
514
- raise 'Dataset not associated with model' unless @record_class
520
+ raise SequelError, 'Dataset not associated with model' unless @record_class
515
521
 
516
522
  count = 0
517
523
  @db.transaction {each {|r| count += 1; r.destroy}}
@@ -531,7 +537,7 @@ class Symbol
531
537
  end
532
538
 
533
539
  def AS(target)
534
- "#{field_name} AS #{target}"
540
+ "#{to_field_name} AS #{target}"
535
541
  end
536
542
 
537
543
  def MIN; "min(#{to_field_name})"; end
@@ -556,4 +562,3 @@ class Symbol
556
562
  "#{to_s}.*"
557
563
  end
558
564
  end
559
-
data/lib/sequel/model.rb CHANGED
@@ -170,7 +170,9 @@ module Sequel
170
170
  def self.each(&block); dataset.each(&block); end
171
171
  def self.all; dataset.all; end
172
172
  def self.filter(*arg); dataset.filter(*arg); end
173
- def self.first; dataset.first; end
173
+ def self.exclude(*arg); dataset.exclude(*arg); end
174
+ def self.order(*arg); dataset.order(*arg); end
175
+ def self.first(*arg); dataset.first(*arg); end
174
176
  def self.count; dataset.count; end
175
177
  def self.map(column); dataset.map(column); end
176
178
  def self.hash_column(column); dataset.hash_column(primary_key, column); end
@@ -254,7 +256,7 @@ module Sequel
254
256
  end
255
257
 
256
258
  def ==(obj)
257
- (obj.class == model) && (obj.pkey == @pkey)
259
+ (obj.class == model) && (obj.values == @values)
258
260
  end
259
261
 
260
262
  def set(values)
@@ -172,7 +172,7 @@ module Sequel
172
172
  Postgres::Dataset.new(self, opts)
173
173
  end
174
174
 
175
- RELATION_QUERY = {:from => :pg_class, :select => :relname}.freeze
175
+ RELATION_QUERY = {:from => [:pg_class], :select => [:relname]}.freeze
176
176
  RELATION_FILTER = "(relkind = 'r') AND (relname !~ '^pg|sql')".freeze
177
177
  SYSTEM_TABLE_REGEXP = /^pg|sql/.freeze
178
178
 
data/lib/sequel/sqlite.rb CHANGED
@@ -101,6 +101,14 @@ module Sequel
101
101
  end
102
102
  self
103
103
  end
104
+
105
+ EXPLAIN = 'EXPLAIN %s'.freeze
106
+
107
+ def explain
108
+ res = []
109
+ @db.result_set(EXPLAIN % select_sql(opts), nil) {|r| res << r}
110
+ res
111
+ end
104
112
  end
105
113
  end
106
114
  end
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.0
2
+ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: sequel
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.0.18
7
- date: 2007-04-13 00:00:00 +03:00
6
+ version: 0.0.19
7
+ date: 2007-04-16 00:00:00 +03:00
8
8
  summary: Concise ORM for Ruby.
9
9
  require_paths:
10
10
  - lib
@@ -35,18 +35,18 @@ files:
35
35
  - bin/sequel
36
36
  - doc/rdoc
37
37
  - lib/sequel
38
- - lib/sequel.rb
39
- - lib/sequel/connection_pool.rb
40
- - lib/sequel/core_ext.rb
38
+ - lib/sequel/pretty_table.rb
39
+ - lib/sequel/model.rb
40
+ - lib/sequel/schema.rb
41
+ - lib/sequel/sqlite.rb
41
42
  - lib/sequel/database.rb
42
43
  - lib/sequel/dataset.rb
43
- - lib/sequel/error.rb
44
- - lib/sequel/model.rb
45
44
  - lib/sequel/mysql.rb
46
45
  - lib/sequel/postgres.rb
47
- - lib/sequel/pretty_table.rb
48
- - lib/sequel/schema.rb
49
- - lib/sequel/sqlite.rb
46
+ - lib/sequel/connection_pool.rb
47
+ - lib/sequel/core_ext.rb
48
+ - lib/sequel/error.rb
49
+ - lib/sequel.rb
50
50
  - CHANGELOG
51
51
  test_files: []
52
52