sequel 0.0.17 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
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