sequel 0.0.17 → 0.0.18

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,5 +1,17 @@
1
+ *0.0.18*
2
+
3
+ * Implemented SequelError and SequelConnectionError classes. ConnectionPool#hold now catches any connection errors and reraises them SequelConnectionError.
4
+
5
+ * Removed duplication in Database#[].
6
+
7
+ * :from and :select options are now always arrays (patch by Alex Bradbury.)
8
+
9
+ * Fixed Dataset#exclude to work correctly (patch and specs by Alex Bradbury.)
10
+
1
11
  *0.0.17*
2
12
 
13
+ * Fixed Postgres::Database#tables to return table names as symbols (caused problem when using Database#table_exists?).
14
+
3
15
  * Fixed Dataset#from to have variable arity, like Dataset#select and Dataset#where (patch by Alex Bradbury.)
4
16
 
5
17
  * Added support for GROUP BY and HAVING clauses (patches by Alex Bradbury.) Refactored Dataset#filter.
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ require 'fileutils'
6
6
  include FileUtils
7
7
 
8
8
  NAME = "sequel"
9
- VERS = "0.0.17"
9
+ VERS = "0.0.18"
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.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  dir = File.join(File.dirname(__FILE__), 'sequel')
2
2
  require File.join(dir, 'core_ext')
3
+ require File.join(dir, 'error')
3
4
  require File.join(dir, 'database')
4
5
  require File.join(dir, 'connection_pool')
5
6
  require File.join(dir, 'schema')
@@ -33,6 +33,8 @@ module Sequel
33
33
  ensure
34
34
  release(t)
35
35
  end
36
+ rescue Exception => e
37
+ raise SequelConnectionError.new(e)
36
38
  end
37
39
 
38
40
  def owned_connection(thread)
@@ -30,13 +30,9 @@ module Sequel
30
30
 
31
31
  # Returns a new dataset with the select method invoked.
32
32
  def select(*args); dataset.select(*args); end
33
-
34
- # Returns a new dataset with the from parameter set. For example,
35
- # db[:posts].each {|p| puts p[:title]}
36
- def [](table)
37
- dataset.from(table)
38
- end
39
33
 
34
+ alias_method :[], :from
35
+
40
36
  def execute(sql)
41
37
  raise RuntimeError
42
38
  end
@@ -81,26 +81,18 @@ module Sequel
81
81
 
82
82
  # Converts a field list into a comma seperated string of field names.
83
83
  def field_list(fields)
84
- case fields
85
- when Array:
86
- if fields.empty?
87
- WILDCARD
88
- else
89
- fields.map {|i| field_name(i)}.join(COMMA_SEPARATOR)
90
- end
91
- when Symbol:
92
- fields.to_field_name
84
+ if fields.empty?
85
+ WILDCARD
93
86
  else
94
- fields
87
+ fields.map {|i| field_name(i)}.join(COMMA_SEPARATOR)
95
88
  end
96
89
  end
97
90
 
98
91
  # Converts an array of sources into a comma separated list.
99
92
  def source_list(source)
100
- case source
101
- when Array: source.join(COMMA_SEPARATOR)
102
- else source
103
- end
93
+ raise 'No source specified for query' unless source
94
+ source.map {|i| i.is_a?(Dataset) ? i.to_table_reference : i}.
95
+ join(COMMA_SEPARATOR)
104
96
  end
105
97
 
106
98
  NULL = "NULL".freeze
@@ -115,7 +107,7 @@ module Sequel
115
107
  when NilClass: NULL
116
108
  when Symbol: v.to_field_name
117
109
  when Array: v.empty? ? NULL : v.map {|i| literal(i)}.join(COMMA_SEPARATOR)
118
- when self.class: SUBQUERY % v.sql
110
+ when Dataset: SUBQUERY % v.sql
119
111
  else
120
112
  raise "can't express #{v.inspect}:#{v.class} as a SQL literal"
121
113
  end
@@ -141,24 +133,27 @@ module Sequel
141
133
  IN_EXPR % [left, literal(right)]
142
134
  when NilClass:
143
135
  NULL_EXPR % left
144
- when self.class:
136
+ when Dataset:
145
137
  IN_EXPR % [left, right.sql]
146
138
  else
147
139
  EQUAL_COND % [left, literal(right)]
148
140
  end
149
141
  end
150
142
 
151
- # Formats a where clause.
143
+ # Formats a where clause. If parenthesize is true, then the whole
144
+ # generated clause will be enclosed in a set of parentheses.
152
145
  def where_list(where, parenthesize = false)
153
146
  case where
154
147
  when Hash:
155
- where.map {|kv| where_condition(*kv)}.join(AND_SEPARATOR)
148
+ parenthesize = false if where.size == 1
149
+ fmt = where.map {|kv| where_condition(*kv)}.join(AND_SEPARATOR)
156
150
  when Array:
157
151
  fmt = where.shift
158
- fmt.gsub('?') {|i| literal(where.shift)}
152
+ fmt.gsub!('?') {|i| literal(where.shift)}
159
153
  else
160
- parenthesize ? "(#{where})" : where
154
+ fmt = where
161
155
  end
156
+ parenthesize ? "(#{fmt})" : fmt
162
157
  end
163
158
 
164
159
  # Formats a join condition.
@@ -172,13 +167,11 @@ module Sequel
172
167
 
173
168
  # Returns a copy of the dataset with the source changed.
174
169
  def from(*source)
175
- source = source.first if source.size == 1
176
170
  dup_merge(:from => source)
177
171
  end
178
172
 
179
173
  # Returns a copy of the dataset with the selected fields changed.
180
174
  def select(*fields)
181
- fields = fields.first if fields.size == 1
182
175
  dup_merge(:select => fields)
183
176
  end
184
177
 
@@ -221,12 +214,28 @@ module Sequel
221
214
  def filter(*cond)
222
215
  clause = (@opts[:group] ? :having : :where)
223
216
  cond = cond.first if cond.size == 1
217
+ parenthesize = !(cond.is_a?(Hash) || cond.is_a?(Array))
224
218
  if @opts[clause]
225
- cond = AND_WHERE % [where_list(@opts[clause]), where_list(cond, true)]
219
+ cond = AND_WHERE % [where_list(@opts[clause]), where_list(cond, parenthesize)]
226
220
  end
227
221
  dup_merge(clause => where_list(cond))
228
222
  end
229
223
 
224
+ NOT_WHERE = "NOT %s".freeze
225
+ AND_NOT_WHERE = "%s AND NOT %s".freeze
226
+
227
+ def exclude(*cond)
228
+ clause = (@opts[:group] ? :having : :where)
229
+ cond = cond.first if cond.size == 1
230
+ parenthesize = !(cond.is_a?(Hash) || cond.is_a?(Array))
231
+ if @opts[clause]
232
+ cond = AND_NOT_WHERE % [where_list(@opts[clause]), where_list(cond, parenthesize)]
233
+ else
234
+ cond = NOT_WHERE % where_list(cond, true)
235
+ end
236
+ dup_merge(clause => cond)
237
+ end
238
+
230
239
  # Returns a copy of the dataset with the where conditions changed. Raises
231
240
  # if the dataset has been grouped. See also #filter
232
241
  def where(*cond)
@@ -247,13 +256,6 @@ module Sequel
247
256
  end
248
257
  end
249
258
 
250
- NOT_WHERE = "NOT %s".freeze
251
-
252
- def exclude(*cond)
253
- cond = cond.first if cond.size == 1
254
- filter(NOT_WHERE % where_list(cond))
255
- end
256
-
257
259
  LEFT_OUTER_JOIN = 'LEFT OUTER JOIN'.freeze
258
260
  INNER_JOIN = 'INNER JOIN'.freeze
259
261
  RIGHT_OUTER_JOIN = 'RIGHT OUTER JOIN'.freeze
@@ -383,8 +385,8 @@ module Sequel
383
385
 
384
386
  if opts[:group]
385
387
  raise "Can't update a grouped dataset"
386
- elsif opts[:from].is_a?(Array) && opts[:from].size > 1
387
- raise "Can't update in a joined dataset"
388
+ elsif (opts[:from].size > 1) or opts[:join_type]
389
+ raise "Can't update a joined dataset"
388
390
  end
389
391
 
390
392
  set_list = values.map {|kv| SET_FORMAT % [kv[0], literal(kv[1])]}.
@@ -424,6 +426,14 @@ module Sequel
424
426
  def count_sql(opts = nil)
425
427
  select_sql(opts ? opts.merge(SELECT_COUNT) : SELECT_COUNT)
426
428
  end
429
+
430
+ def to_table_reference
431
+ if opts.keys == [:from] && opts[:from].size == 1
432
+ opts[:from].first.to_s
433
+ else
434
+ SUBQUERY % sql
435
+ end
436
+ end
427
437
 
428
438
  # aggregates
429
439
  def min(field)
@@ -475,8 +485,8 @@ module Sequel
475
485
  end
476
486
 
477
487
  # Returns the first record matching the condition.
478
- def [](condition)
479
- where(condition).first
488
+ def [](*conditions)
489
+ where(*conditions).first
480
490
  end
481
491
 
482
492
  # Updates all records matching the condition with the values specified.
@@ -0,0 +1,20 @@
1
+ class SequelError < StandardError
2
+ end
3
+
4
+ # This error class is used to wrap exceptions occuring inside calls to
5
+ # ConnectionPool#hold. Sequel wraps any exception raised by the database
6
+ # connection and provides it as a SequelConnectionError. The original
7
+ # exception is provided through SequelConnectionError#original_exception.
8
+ class SequelConnectionError < SequelError
9
+ attr_reader :original_error
10
+
11
+ def initialize(original_error)
12
+ @original_error = original_error
13
+ end
14
+
15
+ def message
16
+ "#{@original_error.class}: #{@original_error.message}"
17
+ end
18
+
19
+ alias_method :to_s, :message
20
+ end
@@ -178,7 +178,7 @@ module Sequel
178
178
 
179
179
 
180
180
  def tables
181
- dataset(RELATION_QUERY).filter(RELATION_FILTER).map(:relname)
181
+ dataset(RELATION_QUERY).filter(RELATION_FILTER).map {|r| r[:relname].to_sym}
182
182
  end
183
183
 
184
184
  def locks
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: sequel
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.0.17
7
- date: 2007-04-10 00:00:00 +03:00
6
+ version: 0.0.18
7
+ date: 2007-04-13 00:00:00 +03:00
8
8
  summary: Concise ORM for Ruby.
9
9
  require_paths:
10
10
  - lib
@@ -40,6 +40,7 @@ files:
40
40
  - lib/sequel/core_ext.rb
41
41
  - lib/sequel/database.rb
42
42
  - lib/sequel/dataset.rb
43
+ - lib/sequel/error.rb
43
44
  - lib/sequel/model.rb
44
45
  - lib/sequel/mysql.rb
45
46
  - lib/sequel/postgres.rb