sequel_core 1.3 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,29 @@
1
+ === 1.4.0 (2008-04-08)
2
+
3
+ * Merge 3 mysql patches from the bugtracker (mvyver) (#200, #201, #202).
4
+
5
+ * Merge 2 postgresql patches from the bugtracker (a...@mellowtone.co.jp) (#211, 212).
6
+
7
+ * Allow overriding of default posgres spec database via ENV['SEQUEL_PG_SPEC_DB'] (jeremyevans).
8
+
9
+ * Allow using the Sequel::Model as the first argument in a dataset join selection (jeremyevans) (#170).
10
+
11
+ * Add simple callback mechanism to make model eager loading implementation easier (jeremyevans).
12
+
13
+ * Added Sequel::Error::InvalidOperation class for invalid operations (#198).
14
+
15
+ * Implemented MySQL::Database#server_version (#199).
16
+
17
+ * Added spec configuration for MySQL socket file.
18
+
19
+ * Fixed transform with array tuples in postgres adapter.
20
+
21
+ * Changed spec configuration to Database objects instead of URIs in order to support custom options for spec databases.
22
+
23
+ * Renamed schema files.
24
+
25
+ * Fixed Dataset#from to work correctly with SQL functions (#193).
26
+
1
27
  === 1.3 (2008-03-08)
2
28
 
3
29
  * Added configuration file for running specs (#186).
data/README CHANGED
@@ -7,18 +7,19 @@ Sequel makes it easy to deal with multiple records without having to break your
7
7
  == Resources
8
8
 
9
9
  * {Project page}[http://code.google.com/p/ruby-sequel/]
10
- * {Source code}[http://ruby-sequel.googlecode.com/svn/]
10
+ * {Source code}[http://github.com/jeremyevans/sequel]
11
11
  * {Bug tracking}[http://code.google.com/p/ruby-sequel/issues/list]
12
12
  * {Google group}[http://groups.google.com/group/sequel-talk]
13
13
  * {RubyForge page}[http://rubyforge.org/projects/sequel/]
14
+ * {API RDoc}[http://sequel.rubyforge.org]
14
15
 
15
16
  To check out the source code:
16
17
 
17
- svn co http://ruby-sequel.googlecode.com/svn/trunk
18
+ git clone git://github.com/jeremyevans/sequel.git
18
19
 
19
20
  === Contact
20
21
 
21
- If you have any comments or suggestions please send an email to ciconia at gmail.com and I'll get back to you.
22
+ If you have any comments or suggestions please post to the Google group.
22
23
 
23
24
  == Installation
24
25
 
@@ -208,7 +209,7 @@ Or calculate a sum:
208
209
 
209
210
  You can also specify descending order
210
211
 
211
- posts.order(:stamp.DESC)
212
+ posts.order(:stamp.desc)
212
213
 
213
214
  === Deleting Records
214
215
 
data/Rakefile CHANGED
@@ -9,7 +9,7 @@ include FileUtils
9
9
  # Configuration
10
10
  ##############################################################################
11
11
  NAME = "sequel_core"
12
- VERS = "1.3"
12
+ VERS = "1.4.0"
13
13
  CLEAN.include ["**/.*.sw?", "pkg/*", ".config", "doc/*", "coverage/*"]
14
14
  RDOC_OPTS = [
15
15
  "--quiet",
@@ -49,10 +49,10 @@ spec = Gem::Specification.new do |s|
49
49
  s.extra_rdoc_files = ["README", "CHANGELOG", "COPYING"]
50
50
  s.rdoc_options += RDOC_OPTS +
51
51
  ["--exclude", "^(examples|extras)\/", "--exclude", "lib/sequel_core.rb"]
52
- s.summary = "The Database Toolkit for Ruby"
52
+ s.summary = "The Database Toolkit for Ruby: Core Library and Adapters"
53
53
  s.description = s.summary
54
- s.author = "Sharon Rosner"
55
- s.email = "ciconia@gmail.com"
54
+ s.author = "Aman Gupta"
55
+ s.email = "themastermind1@gmail.com"
56
56
  s.homepage = "http://sequel.rubyforge.org"
57
57
  s.executables = ["sequel"]
58
58
  s.required_ruby_version = ">= 1.8.4"
@@ -99,14 +99,6 @@ task :uninstall => [:clean] do
99
99
  sh %{sudo gem uninstall #{NAME}}
100
100
  end
101
101
 
102
- task :tag do
103
- cwd = FileUtils.pwd
104
- sh %{rm -rf doc/*}
105
- sh %{rm -rf pkg/*}
106
- sh %{rm -rf coverage/*}
107
- sh %{cd ../.. && svn copy #{cwd} tags/#{NAME}-#{VERS} && svn commit -m "#{NAME}-#{VERS} tag." tags}
108
- end
109
-
110
102
  ##############################################################################
111
103
  # gem and rdoc release
112
104
  ##############################################################################
@@ -75,6 +75,17 @@ module Sequel
75
75
  class Database < Sequel::Database
76
76
  set_adapter_scheme :mysql
77
77
 
78
+ def server_version
79
+ @server_version ||= pool.hold do |conn|
80
+ if conn.respond_to?(:server_version)
81
+ pool.hold {|c| c.server_version}
82
+ else
83
+ get(:version[]) =~ /(\d+)\.(\d+)\.(\d+)/
84
+ ($1.to_i * 10000) + ($2.to_i * 100) + $3.to_i
85
+ end
86
+ end
87
+ end
88
+
78
89
  def serial_primary_key_options
79
90
  {:primary_key => true, :type => :integer, :auto_increment => true}
80
91
  end
@@ -213,8 +224,7 @@ module Sequel
213
224
  # Changes the database in use by issuing a USE statement.
214
225
  def use(db_name)
215
226
  disconnect
216
- @opts[:database] = db_name
217
- self << "USE #{db_name}"
227
+ @opts[:database] = db_name if self << "USE #{db_name}"
218
228
  self
219
229
  end
220
230
  end
@@ -225,6 +235,28 @@ module Sequel
225
235
  TRUE = '1'
226
236
  FALSE = '0'
227
237
 
238
+ # Join processing changed after MySQL v5.0.12. NATURAL
239
+ # joins are SQL:2003 consistent.
240
+ JOIN_TYPES = { :cross => 'INNER JOIN'.freeze,
241
+ :straight => 'STRAIGHT_JOIN'.freeze,
242
+ :natural_left => 'NATURAL LEFT JOIN'.freeze,
243
+ :natural_right => 'NATURAL RIGHT JOIN'.freeze,
244
+ :natural_left_outer => 'NATURAL LEFT OUTER JOIN'.freeze,
245
+ :natural_right_outer => 'NATURAL RIGHT OUTER JOIN'.freeze,
246
+ :left => 'LEFT JOIN'.freeze,
247
+ :right => 'RIGHT JOIN'.freeze,
248
+ :left_outer => 'LEFT OUTER JOIN'.freeze,
249
+ :right_outer => 'RIGHT OUTER JOIN'.freeze,
250
+ :natural_inner => 'NATURAL LEFT JOIN'.freeze,
251
+ # :full_outer => 'FULL OUTER JOIN'.freeze,
252
+ #
253
+ # A full outer join, nor a workaround implementation of
254
+ # :full_outer, is not yet possible in Sequel. See issue
255
+ # #195 which probably depends on issue #113 being
256
+ # resolved.
257
+ :inner => 'INNER JOIN'.freeze
258
+ }
259
+
228
260
  def literal(v)
229
261
  case v
230
262
  when LiteralString
@@ -240,6 +272,46 @@ module Sequel
240
272
  end
241
273
  end
242
274
 
275
+ # Returns a join clause based on the specified join type
276
+ # and condition. MySQL's NATURAL join is 'semantically
277
+ # equivalent to a JOIN with a USING clause that names all
278
+ # columns that exist in both tables. The constraint
279
+ # expression may be nil, so join expression can accept two
280
+ # arguments.
281
+ #
282
+ # === Note
283
+ # Full outer joins (:full_outer) are not implemented in
284
+ # MySQL (as of v6.0), nor is there currently a work around
285
+ # implementation in Sequel. Straight joins with 'ON
286
+ # <condition>' are not yet implemented.
287
+ #
288
+ # === Example
289
+ # @ds = MYSQL_DB[:nodes]
290
+ # @ds.join_expr(:natural_left_outer, :nodes)
291
+ # # 'NATURAL LEFT OUTER JOIN nodes'
292
+ #
293
+ def join_expr(type, table, expr = nil)
294
+ join_type = JOIN_TYPES[type || :inner]
295
+ unless join_type
296
+ raise Error::InvalidJoinType, "Invalid join type: #{type}"
297
+ end
298
+ @opts[:server_version] = @db.server_version unless @opts[:server_version]
299
+ type = :inner if type == :cross && !expr.nil?
300
+ if type.to_s =~ /natural|cross|straight/ && @opts[:server_version] >= 50014
301
+ tbl_factor = table.to_s
302
+ if table.is_a?(Dataset)
303
+ tbl_factor = table.sql << " AS t1"
304
+ end
305
+ if table.is_a?(Array)
306
+ tbl_factor = "( #{literal(table)} )"
307
+ end
308
+ join_string = "#{join_type} " << tbl_factor
309
+ return join_string
310
+ end
311
+
312
+ super
313
+ end
314
+
243
315
  def match_expr(l, r)
244
316
  case r
245
317
  when Regexp
@@ -452,4 +524,4 @@ module Sequel
452
524
  end
453
525
  end
454
526
  end
455
- end
527
+ end
@@ -2,8 +2,8 @@ require 'postgres'
2
2
 
3
3
  class PGconn
4
4
  # the pure-ruby postgres adapter does not have a quote method.
5
- TRUE = 't'.freeze
6
- FALSE = 'f'.freeze
5
+ TRUE = 'true'.freeze
6
+ FALSE = 'false'.freeze
7
7
  NULL = 'NULL'.freeze
8
8
 
9
9
  unless methods.include?('quote')
@@ -47,6 +47,10 @@ class PGconn
47
47
  alias_method :async_exec, :exec
48
48
  end
49
49
 
50
+ unless instance_methods.include?('async_query')
51
+ alias_method :async_query, :query
52
+ end
53
+
50
54
  def execute(sql, &block)
51
55
  q = nil
52
56
  begin
@@ -80,7 +84,7 @@ class PGconn
80
84
  end
81
85
  if seq = @table_sequences[table]
82
86
  r = async_query(SELECT_CURRVAL % seq)
83
- return r[0][0].to_i unless r.nil? || r.empty?
87
+ return r[0][0].to_i unless r.nil? || (r.respond_to?(:empty?) && r.empty?)
84
88
  end
85
89
  nil # primary key sequence not found
86
90
  end
@@ -126,17 +130,17 @@ class PGconn
126
130
 
127
131
  def pkey_and_sequence(table)
128
132
  r = async_query(SELECT_PK_AND_SERIAL_SEQUENCE % table)
129
- return [r[0].first, r[0].last] unless r.nil? or r.empty?
133
+ return [r[0].first, r[0].last] unless r.nil? || (r.respond_to?(:empty?) && r.empty?)
130
134
 
131
135
  r = async_query(SELECT_PK_AND_CUSTOM_SEQUENCE % table)
132
- return [r[0].first, r[0].last] unless r.nil? or r.empty?
136
+ return [r[0].first, r[0].last] unless r.nil? || (r.respond_to?(:empty?) && r.empty?)
133
137
  rescue
134
138
  nil
135
139
  end
136
140
 
137
141
  def primary_key(table)
138
142
  r = async_query(SELECT_PK % table)
139
- pkey = r[0].first unless r.nil? or r.empty?
143
+ pkey = r[0].first unless r.nil? || (r.respond_to?(:empty?) && r.empty?)
140
144
  return pkey.to_sym if pkey
141
145
  rescue
142
146
  nil
@@ -535,6 +539,23 @@ module Sequel
535
539
  end
536
540
  eval("lambda {|r| r.keys = columns; #{tr.join(';')}; r}")
537
541
  end
542
+
543
+ def array_tuples_transform_load(r)
544
+ a = []; a.keys = []
545
+ r.each_pair do |k, v|
546
+ a[k] = (tt = @transform[k]) ? tt[0][v] : v
547
+ end
548
+ a
549
+ end
550
+
551
+ # Applies the value transform for data saved to the database.
552
+ def array_tuples_transform_save(r)
553
+ a = []; a.keys = []
554
+ r.each_pair do |k, v|
555
+ a[k] = (tt = @transform[k]) ? tt[1][v] : v
556
+ end
557
+ a
558
+ end
538
559
  end
539
560
  end
540
561
  end
@@ -0,0 +1,19 @@
1
+ module Sequel
2
+ class Dataset
3
+ module Callback
4
+ # Add a symbol with the name of a method to the list of callbacks for name.
5
+ def add_callback(name, sym)
6
+ cbs = (@opts[:callbacks] ||= {})
7
+ cb = (cbs[name] ||= [])
8
+ cb.push(sym)
9
+ end
10
+
11
+ # Run all callbacks for name with the given args
12
+ def run_callback(name, *args)
13
+ return unless cbs = @opts[:callbacks]
14
+ return unless cb = cbs[name]
15
+ cb.each{|sym| send(sym, *args)}
16
+ end
17
+ end
18
+ end
19
+ end
@@ -42,23 +42,33 @@ module Sequel
42
42
  m.join(COMMA_SEPARATOR)
43
43
  end
44
44
  end
45
-
45
+
46
+ def table_ref(t)
47
+ case t
48
+ when Dataset
49
+ t.to_table_reference
50
+ when Hash
51
+ t.map {|k, v| "#{table_ref(k)} #{table_ref(v)}"}.join(COMMA_SEPARATOR)
52
+ when Symbol, String
53
+ t
54
+ else
55
+ literal(t)
56
+ end
57
+ end
58
+
46
59
  # Converts an array of sources names into into a comma separated list.
47
60
  def source_list(source)
48
61
  if source.nil? || source.empty?
49
62
  raise Error, 'No source specified for query'
50
63
  end
51
64
  auto_alias_count = 0
52
- m = source.map do |i|
53
- case i
65
+ m = source.map do |s|
66
+ case s
54
67
  when Dataset
55
68
  auto_alias_count += 1
56
- i.to_table_reference(auto_alias_count)
57
- when Hash
58
- i.map {|k, v| "#{k.is_a?(Dataset) ? k.to_table_reference : k} #{v}"}.
59
- join(COMMA_SEPARATOR)
69
+ s.to_table_reference(auto_alias_count)
60
70
  else
61
- i
71
+ table_ref(s)
62
72
  end
63
73
  end
64
74
  m.join(COMMA_SEPARATOR)
@@ -356,7 +366,7 @@ module Sequel
356
366
  # if the dataset has not been grouped. See also #filter
357
367
  def having(*cond, &block)
358
368
  unless @opts[:group]
359
- raise Error, "Can only specify a HAVING clause on a grouped dataset"
369
+ raise Error::InvalidOperation, "Can only specify a HAVING clause on a grouped dataset"
360
370
  else
361
371
  @opts[:having] = {}
362
372
  filter(*cond, &block)
@@ -402,6 +412,8 @@ module Sequel
402
412
  unless join_type
403
413
  raise Error::InvalidJoinType, "Invalid join type: #{type}"
404
414
  end
415
+
416
+ table = table.table_name if table.respond_to?(:table_name)
405
417
 
406
418
  join_conditions = {}
407
419
  expr.each do |k, v|
@@ -687,4 +699,4 @@ module Sequel
687
699
  end
688
700
  end
689
701
  end
690
- end
702
+ end
@@ -6,6 +6,7 @@ require 'base64'
6
6
  require File.join(File.dirname(__FILE__), 'dataset/sql')
7
7
  require File.join(File.dirname(__FILE__), 'dataset/sequelizer')
8
8
  require File.join(File.dirname(__FILE__), 'dataset/convenience')
9
+ require File.join(File.dirname(__FILE__), 'dataset/callback')
9
10
 
10
11
  module Sequel
11
12
  # A Dataset represents a view of a the data in a database, constrained by
@@ -69,6 +70,7 @@ module Sequel
69
70
  include Sequelizer
70
71
  include SQL
71
72
  include Convenience
73
+ include Callback
72
74
 
73
75
  attr_accessor :db
74
76
  attr_accessor :opts
@@ -80,6 +82,7 @@ module Sequel
80
82
  def all(opts = nil, &block)
81
83
  a = []
82
84
  each(opts) {|r| a << r}
85
+ run_callback(:post_load, a)
83
86
  a.each(&block) if block
84
87
  a
85
88
  end
@@ -14,6 +14,9 @@ module Sequel
14
14
 
15
15
  # Represents an Invalid transform.
16
16
  class InvalidTransform < Error ; end
17
+
18
+ # Raised on an invalid operation.
19
+ class InvalidOperation < Error; end
17
20
 
18
21
  # Represents an Invalid filter.
19
22
  class InvalidFilter < Error ; end
File without changes
@@ -3,6 +3,6 @@ module Sequel
3
3
  end
4
4
  end
5
5
 
6
- require File.join(File.dirname(__FILE__), 'schema/schema_sql')
7
- require File.join(File.dirname(__FILE__), 'schema/schema_generator')
6
+ require File.join(File.dirname(__FILE__), 'schema/sql')
7
+ require File.join(File.dirname(__FILE__), 'schema/generator')
8
8
 
@@ -1,9 +1,10 @@
1
1
  require File.join(File.dirname(__FILE__), '../../lib/sequel_core')
2
2
  require File.join(File.dirname(__FILE__), '../spec_helper.rb')
3
3
 
4
- unless defined?(INFORMIX_URL); INFORMIX_URL = 'informix://localhost/mydb' ;end
4
+ unless defined?(INFORMIX_DB)
5
+ INFORMIX_DB = Sequel('informix://localhost/mydb')
6
+ end
5
7
 
6
- INFORMIX_DB = Sequel(INFORMIX_URL)
7
8
  if INFORMIX_DB.table_exists?(:test)
8
9
  INFORMIX_DB.drop_table :test
9
10
  end
@@ -2,9 +2,17 @@ require File.join(File.dirname(__FILE__), '../../lib/sequel_core')
2
2
  require File.join(File.dirname(__FILE__), '../spec_helper.rb')
3
3
  require 'logger'
4
4
 
5
- unless defined?(MYSQL_URL); MYSQL_URL = 'mysql://root@localhost/sandbox' ;end
5
+ unless defined?(MYSQL_DB)
6
+ MYSQL_URL = 'mysql://root@localhost/sandbox' unless defined? MYSQL_URL
7
+ MYSQL_DB = Sequel(MYSQL_URL)
8
+ end
9
+ unless defined?(MYSQL_SOCKET_FILE)
10
+ MYSQL_SOCKET_FILE = '/tmp/mysql.sock'
11
+ end
12
+
13
+ MYSQL_URI = URI.parse(MYSQL_DB.uri)
14
+ MYSQL_DB_NAME = MYSQL_URI.path =~ /\/(.*)/ && $1
6
15
 
7
- MYSQL_DB = Sequel(MYSQL_URL)
8
16
  MYSQL_DB.drop_table(:items) if MYSQL_DB.table_exists?(:items)
9
17
  MYSQL_DB.drop_table(:test2) if MYSQL_DB.table_exists?(:test2)
10
18
  MYSQL_DB.create_table :items do
@@ -28,6 +36,10 @@ context "A MySQL database" do
28
36
  @db.pool.size.should == 0
29
37
  end
30
38
 
39
+ specify "should provide the server version" do
40
+ @db.server_version.should >= 40000
41
+ end
42
+
31
43
  specify "should support sequential primary keys" do
32
44
  @db.create_table!(:with_pk) {primary_key :id; text :name}
33
45
  @db[:with_pk] << {:name => 'abc'}
@@ -267,6 +279,53 @@ end
267
279
  # end
268
280
  # end
269
281
  #
282
+ context "MySQL join expressions" do
283
+ setup do
284
+ @ds = MYSQL_DB[:nodes]
285
+ @ds.db.meta_def(:server_version) {50014}
286
+ end
287
+
288
+ specify "should raise error for :full_outer join requests." do
289
+ lambda{@ds.join_expr(:full_outer, :nodes)}.should raise_error(Sequel::Error::InvalidJoinType)
290
+ end
291
+ specify "should support natural left joins" do
292
+ @ds.join_expr(:natural_left, :nodes).should == \
293
+ 'NATURAL LEFT JOIN nodes'
294
+ end
295
+ specify "should support natural right joins" do
296
+ @ds.join_expr(:natural_right, :nodes).should == \
297
+ 'NATURAL RIGHT JOIN nodes'
298
+ end
299
+ specify "should support natural left outer joins" do
300
+ @ds.join_expr(:natural_left_outer, :nodes).should == \
301
+ 'NATURAL LEFT OUTER JOIN nodes'
302
+ end
303
+ specify "should support natural right outer joins" do
304
+ @ds.join_expr(:natural_right_outer, :nodes).should == \
305
+ 'NATURAL RIGHT OUTER JOIN nodes'
306
+ end
307
+ specify "should support natural inner joins" do
308
+ @ds.join_expr(:natural_inner, :nodes).should == \
309
+ 'NATURAL LEFT JOIN nodes'
310
+ end
311
+ specify "should support cross joins (equivalent to inner join in MySQL, not in std SQL)" do
312
+ @ds.join_expr(:cross, :nodes).should == \
313
+ 'INNER JOIN nodes'
314
+ end
315
+ specify "should support straight joins (force left table to be read before right)" do
316
+ @ds.join_expr(:straight, :nodes).should == \
317
+ 'STRAIGHT_JOIN nodes'
318
+ end
319
+ specify "should support natural joins on multiple tables." do
320
+ @ds.join_expr(:natural_left_outer, [:nodes, :branches]).should == \
321
+ 'NATURAL LEFT OUTER JOIN ( `nodes`, `branches` )'
322
+ end
323
+ specify "should support straight joins on multiple tables." do
324
+ @ds.join_expr(:straight, [:nodes,:branches]).should == \
325
+ 'STRAIGHT_JOIN ( `nodes`, `branches` )'
326
+ end
327
+ end
328
+
270
329
  context "Joined MySQL dataset" do
271
330
  setup do
272
331
  @ds = MYSQL_DB[:nodes].join(:attributes, :node_id => :id)
@@ -391,17 +450,17 @@ end
391
450
 
392
451
  context "A MySQL database" do
393
452
  specify "should accept a socket option" do
394
- db = Sequel.mysql('sandbox', :host => 'localhost', :user => 'root', :socket => '/tmp/mysql.sock')
453
+ db = Sequel.mysql(MYSQL_DB_NAME, :host => 'localhost', :user => 'root', :socket => MYSQL_SOCKET_FILE)
395
454
  proc {db.test_connection}.should_not raise_error
396
455
  end
397
456
 
398
457
  specify "should accept a socket option without host option" do
399
- db = Sequel.mysql('sandbox', :user => 'root', :socket => '/tmp/mysql.sock')
458
+ db = Sequel.mysql(MYSQL_DB_NAME, :user => 'root', :socket => MYSQL_SOCKET_FILE)
400
459
  proc {db.test_connection}.should_not raise_error
401
460
  end
402
461
 
403
462
  specify "should fail to connect with invalid socket" do
404
- db = Sequel.mysql('sandbox', :host => 'localhost', :user => 'root', :socket => 'blah')
463
+ db = Sequel.mysql(MYSQL_DB_NAME, :host => 'localhost', :user => 'root', :socket => 'blah')
405
464
  proc {db.test_connection}.should raise_error
406
465
  end
407
466
  end
@@ -590,4 +649,4 @@ context "MySQL::Dataset#replace" do
590
649
  @d.replace(:id => 111, :value => 333)
591
650
  @d.all.should == [{:id => 111, :value => 333}]
592
651
  end
593
- end
652
+ end
@@ -1,9 +1,9 @@
1
1
  require File.join(File.dirname(__FILE__), '../../lib/sequel_core')
2
2
  require File.join(File.dirname(__FILE__), '../spec_helper.rb')
3
3
 
4
- unless defined?(ORACLE_URL); ORACLE_URL = 'oracle://hr:hr@localhost/XE' ;end
5
-
6
- ORACLE_DB = Sequel(ORACLE_URL)
4
+ unless defined?(ORACLE_DB)
5
+ ORACLE_DB = Sequel('oracle://hr:hr@localhost/XE')
6
+ end
7
7
 
8
8
  if ORACLE_DB.table_exists?(:items)
9
9
  ORACLE_DB.drop_table :items
@@ -1,25 +1,25 @@
1
1
  require File.join(File.dirname(__FILE__), '../../lib/sequel_core')
2
2
  require File.join(File.dirname(__FILE__), '../spec_helper.rb')
3
3
 
4
- unless defined?(POSTGRES_URL); POSTGRES_URL = 'postgres://postgres:postgres@localhost:5432/reality_spec' ;end
5
-
4
+ unless defined?(POSTGRES_DB)
5
+ POSTGRES_DB = Sequel(ENV['SEQUEL_PG_SPEC_DB']||'postgres://postgres:postgres@localhost:5432/reality_spec')
6
+ end
6
7
 
7
- PGSQL_DB = Sequel(POSTGRES_URL)
8
- PGSQL_DB.drop_table(:test) if PGSQL_DB.table_exists?(:test)
9
- PGSQL_DB.drop_table(:test2) if PGSQL_DB.table_exists?(:test2)
8
+ POSTGRES_DB.drop_table(:test) if POSTGRES_DB.table_exists?(:test)
9
+ POSTGRES_DB.drop_table(:test2) if POSTGRES_DB.table_exists?(:test2)
10
10
 
11
- PGSQL_DB.create_table :test do
11
+ POSTGRES_DB.create_table :test do
12
12
  text :name
13
13
  integer :value, :index => true
14
14
  end
15
- PGSQL_DB.create_table :test2 do
15
+ POSTGRES_DB.create_table :test2 do
16
16
  text :name
17
17
  integer :value
18
18
  end
19
19
 
20
20
  context "A PostgreSQL database" do
21
21
  setup do
22
- @db = PGSQL_DB
22
+ @db = POSTGRES_DB
23
23
  end
24
24
 
25
25
  specify "should provide disconnect functionality" do
@@ -36,7 +36,7 @@ end
36
36
 
37
37
  context "A PostgreSQL dataset" do
38
38
  setup do
39
- @d = PGSQL_DB[:test]
39
+ @d = POSTGRES_DB[:test]
40
40
  @d.delete # remove all records
41
41
  end
42
42
 
@@ -147,7 +147,7 @@ context "A PostgreSQL dataset" do
147
147
  end
148
148
 
149
149
  specify "should support transactions" do
150
- PGSQL_DB.transaction do
150
+ POSTGRES_DB.transaction do
151
151
  @d << {:name => 'abc', :value => 1}
152
152
  end
153
153
 
@@ -169,7 +169,7 @@ end
169
169
 
170
170
  context "A PostgreSQL dataset in array tuples mode" do
171
171
  setup do
172
- @d = PGSQL_DB[:test]
172
+ @d = POSTGRES_DB[:test]
173
173
  @d.delete # remove all records
174
174
  Sequel.use_array_tuples
175
175
  end
@@ -215,7 +215,7 @@ end
215
215
 
216
216
  context "A PostgreSQL database" do
217
217
  setup do
218
- @db = PGSQL_DB
218
+ @db = POSTGRES_DB
219
219
  end
220
220
 
221
221
  specify "should support add_column operations" do
@@ -259,44 +259,44 @@ context "A PostgreSQL database" do
259
259
  end
260
260
 
261
261
  specify "should support fulltext indexes" do
262
- g = Sequel::Schema::Generator.new(PGSQL_DB) do
262
+ g = Sequel::Schema::Generator.new(POSTGRES_DB) do
263
263
  text :title
264
264
  text :body
265
265
  full_text_index [:title, :body]
266
266
  end
267
- PGSQL_DB.create_table_sql_list(:posts, *g.create_info).should == [
267
+ POSTGRES_DB.create_table_sql_list(:posts, *g.create_info).should == [
268
268
  "CREATE TABLE posts (\"title\" text, \"body\" text)",
269
269
  "CREATE INDEX posts_title_body_index ON posts USING gin(to_tsvector(\"title\" || \"body\"))"
270
270
  ]
271
271
  end
272
272
 
273
273
  specify "should support fulltext indexes with a specific language" do
274
- g = Sequel::Schema::Generator.new(PGSQL_DB) do
274
+ g = Sequel::Schema::Generator.new(POSTGRES_DB) do
275
275
  text :title
276
276
  text :body
277
277
  full_text_index [:title, :body], :language => 'french'
278
278
  end
279
- PGSQL_DB.create_table_sql_list(:posts, *g.create_info).should == [
279
+ POSTGRES_DB.create_table_sql_list(:posts, *g.create_info).should == [
280
280
  "CREATE TABLE posts (\"title\" text, \"body\" text)",
281
281
  "CREATE INDEX posts_title_body_index ON posts USING gin(to_tsvector('french', \"title\" || \"body\"))"
282
282
  ]
283
283
  end
284
284
 
285
285
  specify "should support full_text_search" do
286
- PGSQL_DB[:posts].full_text_search(:title, 'ruby').sql.should ==
286
+ POSTGRES_DB[:posts].full_text_search(:title, 'ruby').sql.should ==
287
287
  "SELECT * FROM posts WHERE (to_tsvector(\"title\") @@ to_tsquery('ruby'))"
288
288
 
289
- PGSQL_DB[:posts].full_text_search([:title, :body], ['ruby', 'sequel']).sql.should ==
289
+ POSTGRES_DB[:posts].full_text_search([:title, :body], ['ruby', 'sequel']).sql.should ==
290
290
  "SELECT * FROM posts WHERE (to_tsvector(\"title\" || \"body\") @@ to_tsquery('ruby | sequel'))"
291
291
 
292
- PGSQL_DB[:posts].full_text_search(:title, 'ruby', :language => 'french').sql.should ==
292
+ POSTGRES_DB[:posts].full_text_search(:title, 'ruby', :language => 'french').sql.should ==
293
293
  "SELECT * FROM posts WHERE (to_tsvector('french', \"title\") @@ to_tsquery('french', 'ruby'))"
294
294
  end
295
295
  end
296
296
 
297
297
  context "Postgres::Dataset#multi_insert_sql / #import" do
298
298
  setup do
299
- @ds = PGSQL_DB[:test]
299
+ @ds = POSTGRES_DB[:test]
300
300
  end
301
301
 
302
302
  specify "should return separate insert statements if server_version < 80200" do
@@ -321,4 +321,4 @@ context "Postgres::Dataset#multi_insert_sql / #import" do
321
321
  'INSERT INTO test ("x", "y") VALUES (1, 2), (3, 4)'
322
322
  ]
323
323
  end
324
- end
324
+ end
@@ -1,9 +1,10 @@
1
1
  require File.join(File.dirname(__FILE__), '../../lib/sequel_core')
2
2
  require File.join(File.dirname(__FILE__), '../spec_helper.rb')
3
3
 
4
- unless defined?(SQLITE_URL); SQLITE_URL = 'sqlite:/' ;end
4
+ unless defined?(SQLITE_DB)
5
+ SQLITE_DB = Sequel('sqlite:/')
6
+ end
5
7
 
6
- SQLITE_DB = Sequel(SQLITE_URL)
7
8
  SQLITE_DB.create_table :items do
8
9
  integer :id, :primary_key => true, :auto_increment => true
9
10
  text :name
data/spec/dataset_spec.rb CHANGED
@@ -199,11 +199,11 @@ context "A dataset with multiple tables in its FROM clause" do
199
199
  end
200
200
 
201
201
  specify "should raise on #update_sql" do
202
- proc {@dataset.update_sql(:a=>1)}.should raise_error
202
+ proc {@dataset.update_sql(:a=>1)}.should raise_error(Sequel::Error::InvalidOperation)
203
203
  end
204
204
 
205
205
  specify "should raise on #delete_sql" do
206
- proc {@dataset.delete_sql}.should raise_error
206
+ proc {@dataset.delete_sql}.should raise_error(Sequel::Error::InvalidOperation)
207
207
  end
208
208
 
209
209
  specify "should generate a select query FROM all specified tables" do
@@ -508,7 +508,7 @@ context "Dataset#having" do
508
508
  end
509
509
 
510
510
  specify "should raise if the dataset is not grouped" do
511
- proc {@dataset.having('avg(gdp) > 10')}.should raise_error
511
+ proc {@dataset.having('avg(gdp) > 10')}.should raise_error(Sequel::Error::InvalidOperation)
512
512
  end
513
513
 
514
514
  specify "should affect select statements" do
@@ -665,6 +665,12 @@ context "Dataset#from" do
665
665
  @dataset.from(:a => :b).sql.should ==
666
666
  "SELECT * FROM a b"
667
667
 
668
+ @dataset.from(:a => 'b').sql.should ==
669
+ "SELECT * FROM a b"
670
+
671
+ @dataset.from(:a => :c[:d]).sql.should ==
672
+ "SELECT * FROM a c(d)"
673
+
668
674
  @dataset.from(@dataset.from(:a).group(:b) => :c).sql.should ==
669
675
  "SELECT * FROM (SELECT * FROM a GROUP BY b) c"
670
676
  end
@@ -677,6 +683,20 @@ context "Dataset#from" do
677
683
  specify "should raise if no source is given" do
678
684
  proc {@dataset.from(@dataset.from).select_sql}.should raise_error(Sequel::Error)
679
685
  end
686
+
687
+ specify "should accept sql functions" do
688
+ @dataset.from(:abc[:def]).select_sql.should ==
689
+ "SELECT * FROM abc(def)"
690
+
691
+ @dataset.from(:a|:i).select_sql.should ==
692
+ "SELECT * FROM a[i]"
693
+
694
+ @dataset.from(:generate_series[1, 2].as(:a[:i])).select_sql.should ==
695
+ "SELECT * FROM generate_series(1, 2) AS a(i)"
696
+
697
+ @dataset.from(:generate_series[1, 2] => :a[:i]).select_sql.should ==
698
+ "SELECT * FROM generate_series(1, 2) a(i)"
699
+ end
680
700
  end
681
701
 
682
702
  context "Dataset#select" do
@@ -1229,6 +1249,14 @@ context "Dataset#join_table" do
1229
1249
  @d.join_table(:left_outer, ds, :item_id => :id).sql.should ==
1230
1250
  'SELECT * FROM items LEFT OUTER JOIN (SELECT * FROM categories WHERE (active = \'t\')) t1 ON (t1.item_id = items.id)'
1231
1251
  end
1252
+
1253
+ specify "should support joining objects that respond to :table_name" do
1254
+ ds = Object.new
1255
+ def ds.table_name; :categories end
1256
+
1257
+ @d.join(ds, :item_id => :id).sql.should ==
1258
+ 'SELECT * FROM items INNER JOIN categories ON (categories.item_id = items.id)'
1259
+ end
1232
1260
  end
1233
1261
 
1234
1262
  context "Dataset#[]=" do
@@ -2943,4 +2971,4 @@ context "Dataset#grep" do
2943
2971
  @ds.grep(:title, [/^ruby/, 'ruby']).sql.should ==
2944
2972
  "SELECT * FROM posts WHERE ((title =~ '^ruby') OR (title LIKE 'ruby'))"
2945
2973
  end
2946
- end
2974
+ end
@@ -1,6 +1,7 @@
1
- # connection URL's for running adapter specs
2
- INFORMIX_URL = 'informix://localhost/mydb'
3
- MYSQL_URL = 'mysql://root@localhost/sandbox'
4
- ORACLE_URL = 'oracle://hr:hr@localhost/XE'
5
- POSTGRES_URL = 'postgres://postgres:postgres@localhost:5432/reality_spec'
6
- SQLITE_URL = 'sqlite:/'
1
+ # database objects for running adapter specs
2
+ # INFORMIX_DB = Sequel('informix://localhost/mydb')
3
+ # MYSQL_DB = Sequel('mysql://root@localhost/sandbox')
4
+ # MYSQL_SOCKET_FILE = '/tmp/mysql.sock'
5
+ # ORACLE_DB = Sequel('oracle://hr:hr@localhost/XE')
6
+ # POSTGRES_DB = Sequel('postgres://postgres:postgres@localhost:5432/reality_spec')
7
+ # SQLITE_DB = Sequel('sqlite:/')
metadata CHANGED
@@ -1,83 +1,39 @@
1
1
  --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
2
4
  name: sequel_core
3
5
  version: !ruby/object:Gem::Version
4
- version: "1.3"
5
- platform: ruby
6
- authors:
7
- - Sharon Rosner
6
+ version: 1.4.0
7
+ date: 2008-04-08 00:00:00 -07:00
8
+ summary: "The Database Toolkit for Ruby: Core Library and Adapters"
9
+ require_paths:
10
+ - lib
11
+ email: themastermind1@gmail.com
12
+ homepage: http://sequel.rubyforge.org
13
+ rubyforge_project: sequel
14
+ description: "The Database Toolkit for Ruby: Core Library and Adapters"
8
15
  autorequire:
9
- bindir: bin
10
- cert_chain: []
11
-
12
- date: 2008-03-08 00:00:00 +02:00
13
16
  default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: metaid
17
- version_requirement:
18
- version_requirements: !ruby/object:Gem::Requirement
19
- requirements:
20
- - - ">="
21
- - !ruby/object:Gem::Version
22
- version: "0"
23
- version:
24
- - !ruby/object:Gem::Dependency
25
- name: assistance
26
- version_requirement:
27
- version_requirements: !ruby/object:Gem::Requirement
28
- requirements:
29
- - - ">="
30
- - !ruby/object:Gem::Version
31
- version: "0.1"
32
- version:
33
- - !ruby/object:Gem::Dependency
34
- name: RubyInline
35
- version_requirement:
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: 3.6.6
41
- version:
42
- - !ruby/object:Gem::Dependency
43
- name: ParseTree
44
- version_requirement:
45
- version_requirements: !ruby/object:Gem::Requirement
46
- requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: 2.1.1
50
- version:
51
- - !ruby/object:Gem::Dependency
52
- name: ruby2ruby
53
- version_requirement:
54
- version_requirements: !ruby/object:Gem::Requirement
55
- requirements:
56
- - - ">="
57
- - !ruby/object:Gem::Version
58
- version: "0"
59
- version:
60
- description: The Database Toolkit for Ruby
61
- email: ciconia@gmail.com
62
- executables:
63
- - sequel
64
- extensions: []
65
-
66
- extra_rdoc_files:
67
- - README
68
- - CHANGELOG
69
- - COPYING
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.8.4
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Aman Gupta
70
31
  files:
71
32
  - COPYING
72
33
  - README
73
34
  - Rakefile
74
35
  - bin/sequel
75
36
  - spec/adapters
76
- - spec/adapters/informix_spec.rb
77
- - spec/adapters/mysql_spec.rb
78
- - spec/adapters/oracle_spec.rb
79
- - spec/adapters/postgres_spec.rb
80
- - spec/adapters/sqlite_spec.rb
81
37
  - spec/array_keys_spec.rb
82
38
  - spec/core_ext_spec.rb
83
39
  - spec/core_sql_spec.rb
@@ -93,8 +49,27 @@ files:
93
49
  - spec/spec_config.rb.example
94
50
  - spec/spec_helper.rb
95
51
  - spec/worker_spec.rb
52
+ - spec/adapters/informix_spec.rb
53
+ - spec/adapters/mysql_spec.rb
54
+ - spec/adapters/oracle_spec.rb
55
+ - spec/adapters/postgres_spec.rb
56
+ - spec/adapters/sqlite_spec.rb
57
+ - lib/sequel_core.rb
96
58
  - lib/sequel_core
97
59
  - lib/sequel_core/adapters
60
+ - lib/sequel_core/array_keys.rb
61
+ - lib/sequel_core/core_ext.rb
62
+ - lib/sequel_core/core_sql.rb
63
+ - lib/sequel_core/database.rb
64
+ - lib/sequel_core/dataset.rb
65
+ - lib/sequel_core/dataset
66
+ - lib/sequel_core/exceptions.rb
67
+ - lib/sequel_core/migration.rb
68
+ - lib/sequel_core/model.rb
69
+ - lib/sequel_core/pretty_table.rb
70
+ - lib/sequel_core/schema.rb
71
+ - lib/sequel_core/schema
72
+ - lib/sequel_core/worker.rb
98
73
  - lib/sequel_core/adapters/adapter_skeleton.rb
99
74
  - lib/sequel_core/adapters/ado.rb
100
75
  - lib/sequel_core/adapters/db2.rb
@@ -108,29 +83,15 @@ files:
108
83
  - lib/sequel_core/adapters/oracle.rb
109
84
  - lib/sequel_core/adapters/postgres.rb
110
85
  - lib/sequel_core/adapters/sqlite.rb
111
- - lib/sequel_core/array_keys.rb
112
- - lib/sequel_core/core_ext.rb
113
- - lib/sequel_core/core_sql.rb
114
- - lib/sequel_core/database.rb
115
- - lib/sequel_core/dataset
86
+ - lib/sequel_core/dataset/callback.rb
116
87
  - lib/sequel_core/dataset/convenience.rb
117
88
  - lib/sequel_core/dataset/sequelizer.rb
118
89
  - lib/sequel_core/dataset/sql.rb
119
- - lib/sequel_core/dataset.rb
120
- - lib/sequel_core/exceptions.rb
121
- - lib/sequel_core/migration.rb
122
- - lib/sequel_core/model.rb
123
- - lib/sequel_core/pretty_table.rb
124
- - lib/sequel_core/schema
125
- - lib/sequel_core/schema/schema_generator.rb
126
- - lib/sequel_core/schema/schema_sql.rb
127
- - lib/sequel_core/schema.rb
128
- - lib/sequel_core/worker.rb
129
- - lib/sequel_core.rb
90
+ - lib/sequel_core/schema/generator.rb
91
+ - lib/sequel_core/schema/sql.rb
130
92
  - CHANGELOG
131
- has_rdoc: true
132
- homepage: http://sequel.rubyforge.org
133
- post_install_message:
93
+ test_files: []
94
+
134
95
  rdoc_options:
135
96
  - --quiet
136
97
  - --title
@@ -145,26 +106,59 @@ rdoc_options:
145
106
  - ^(examples|extras)/
146
107
  - --exclude
147
108
  - lib/sequel_core.rb
148
- require_paths:
149
- - lib
150
- required_ruby_version: !ruby/object:Gem::Requirement
151
- requirements:
152
- - - ">="
153
- - !ruby/object:Gem::Version
154
- version: 1.8.4
155
- version:
156
- required_rubygems_version: !ruby/object:Gem::Requirement
157
- requirements:
158
- - - ">="
159
- - !ruby/object:Gem::Version
160
- version: "0"
161
- version:
162
- requirements: []
109
+ extra_rdoc_files:
110
+ - README
111
+ - CHANGELOG
112
+ - COPYING
113
+ executables:
114
+ - sequel
115
+ extensions: []
163
116
 
164
- rubyforge_project: sequel
165
- rubygems_version: 1.0.1
166
- signing_key:
167
- specification_version: 2
168
- summary: The Database Toolkit for Ruby
169
- test_files: []
117
+ requirements: []
170
118
 
119
+ dependencies:
120
+ - !ruby/object:Gem::Dependency
121
+ name: metaid
122
+ version_requirement:
123
+ version_requirements: !ruby/object:Gem::Version::Requirement
124
+ requirements:
125
+ - - ">"
126
+ - !ruby/object:Gem::Version
127
+ version: 0.0.0
128
+ version:
129
+ - !ruby/object:Gem::Dependency
130
+ name: assistance
131
+ version_requirement:
132
+ version_requirements: !ruby/object:Gem::Version::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: "0.1"
137
+ version:
138
+ - !ruby/object:Gem::Dependency
139
+ name: RubyInline
140
+ version_requirement:
141
+ version_requirements: !ruby/object:Gem::Version::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: 3.6.6
146
+ version:
147
+ - !ruby/object:Gem::Dependency
148
+ name: ParseTree
149
+ version_requirement:
150
+ version_requirements: !ruby/object:Gem::Version::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: 2.1.1
155
+ version:
156
+ - !ruby/object:Gem::Dependency
157
+ name: ruby2ruby
158
+ version_requirement:
159
+ version_requirements: !ruby/object:Gem::Version::Requirement
160
+ requirements:
161
+ - - ">"
162
+ - !ruby/object:Gem::Version
163
+ version: 0.0.0
164
+ version: