sequel 3.24.1 → 3.25.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -424,7 +424,7 @@ module Sequel
424
424
  @current = opts[:current] || current_migration_version
425
425
 
426
426
  raise(Error, "No current version available") unless current
427
- raise(Error, "No target version available") unless target
427
+ raise(Error, "No target version available, probably because no migration files found or filenames don't follow the migration filename convention") unless target
428
428
 
429
429
  @direction = current < target ? :up : :down
430
430
  @migrations = get_migrations
@@ -326,9 +326,9 @@ module Sequel
326
326
  unless @plugins.include?(m)
327
327
  @plugins << m
328
328
  m.apply(self, *args, &blk) if m.respond_to?(:apply)
329
- include(m::InstanceMethods) if m.const_defined?("InstanceMethods")
330
- extend(m::ClassMethods)if m.const_defined?("ClassMethods")
331
- if m.const_defined?("DatasetMethods")
329
+ include(m::InstanceMethods) if plugin_module_defined?(m, :InstanceMethods)
330
+ extend(m::ClassMethods)if plugin_module_defined?(m, :ClassMethods)
331
+ if plugin_module_defined?(m, :DatasetMethods)
332
332
  dataset.extend(m::DatasetMethods) if @dataset
333
333
  dataset_method_modules << m::DatasetMethods
334
334
  meths = m::DatasetMethods.public_instance_methods.reject{|x| NORMAL_METHOD_NAME_REGEXP !~ x.to_s}
@@ -337,7 +337,7 @@ module Sequel
337
337
  end
338
338
  m.configure(self, *args, &blk) if m.respond_to?(:configure)
339
339
  end
340
-
340
+
341
341
  # Returns primary key attribute hash. If using a composite primary key
342
342
  # value such be an array with values for each primary key in the correct
343
343
  # order. For a standard primary key, value should be an object with a
@@ -419,7 +419,7 @@ module Sequel
419
419
  def set_dataset(ds, opts={})
420
420
  inherited = opts[:inherited]
421
421
  @dataset = case ds
422
- when Symbol
422
+ when Symbol, SQL::Identifier, SQL::QualifiedIdentifier, SQL::AliasedExpression
423
423
  @simple_table = db.literal(ds)
424
424
  db[ds]
425
425
  when Dataset
@@ -427,7 +427,7 @@ module Sequel
427
427
  @db = ds.db
428
428
  ds
429
429
  else
430
- raise(Error, "Model.set_dataset takes a Symbol or a Sequel::Dataset")
430
+ raise(Error, "Model.set_dataset takes one of the following classes as an argument: Symbol, SQL::Identifier, SQL::QualifiedIdentifier, SQL::AliasedExpression, Dataset")
431
431
  end
432
432
  @dataset.row_proc = Proc.new{|r| load(r)}
433
433
  @require_modification = Sequel::Model.require_modification.nil? ? @dataset.provides_accurate_rows_matched? : Sequel::Model.require_modification
@@ -658,6 +658,15 @@ module Sequel
658
658
  Sequel::Plugins.const_get(module_name)
659
659
  end
660
660
 
661
+ # Check if the plugin module +plugin+ defines the constant named by +submod+.
662
+ def plugin_module_defined?(plugin, submod)
663
+ if RUBY_VERSION >= '1.9'
664
+ plugin.const_defined?(submod, false)
665
+ else
666
+ plugin.const_defined?(submod)
667
+ end
668
+ end
669
+
661
670
  # Find the row in the dataset that matches the primary key. Uses
662
671
  # a static SQL optimization if the table and primary key are simple.
663
672
  def primary_key_lookup(pk)
@@ -40,7 +40,7 @@ module Sequel
40
40
  def full_messages
41
41
  inject([]) do |m, kv|
42
42
  att, errors = *kv
43
- errors.each {|e| m << "#{Array(att).join(ATTRIBUTE_JOINER)} #{e}"}
43
+ errors.each {|e| m << (e.is_a?(LiteralString) ? e : "#{Array(att).join(ATTRIBUTE_JOINER)} #{e}")}
44
44
  m
45
45
  end
46
46
  end
@@ -56,6 +56,7 @@ module Sequel
56
56
  _join_table_dataset(opts).filter(opts[:left_key]=>send(opts[:left_primary_key])).select_map(opts[:right_key])
57
57
  end
58
58
  def_association_pks_setter(opts) do |pks|
59
+ pks = convert_pk_array(opts, pks)
59
60
  checked_transaction do
60
61
  ds = _join_table_dataset(opts).filter(opts[:left_key]=>send(opts[:left_primary_key]))
61
62
  ds.exclude(opts[:right_key]=>pks).delete
@@ -74,6 +75,7 @@ module Sequel
74
75
  send(opts.dataset_method).select_map(opts.associated_class.primary_key)
75
76
  end
76
77
  def_association_pks_setter(opts) do |pks|
78
+ pks = convert_pk_array(opts, pks)
77
79
  checked_transaction do
78
80
  ds = send(opts.dataset_method)
79
81
  primary_key = opts.associated_class.primary_key
@@ -84,6 +86,20 @@ module Sequel
84
86
  end
85
87
  end
86
88
  end
89
+
90
+ module InstanceMethods
91
+ private
92
+
93
+ # If the associated class's primary key column type is integer,
94
+ # typecast all provided values to integer before using them.
95
+ def convert_pk_array(opts, pks)
96
+ if klass = opts.associated_class and sch = klass.db_schema and col = sch[klass.primary_key] and col[:type] == :integer
97
+ pks.map{|pk| model.db.typecast_value(:integer, pk)}
98
+ else
99
+ pks
100
+ end
101
+ end
102
+ end
87
103
  end
88
104
  end
89
105
  end
@@ -1,6 +1,6 @@
1
1
  module Sequel
2
2
  module Plugins
3
- # The update_primary_key plugin allows you to modify an objects
3
+ # The update_primary_key plugin allows you to modify an object's
4
4
  # primary key and then save the record. Sequel does not work
5
5
  # correctly with primary key modifications by default. Sequel
6
6
  # is designed to work with surrogate primary keys that never need to be
@@ -3,10 +3,10 @@ module Sequel
3
3
  MAJOR = 3
4
4
  # The minor version of Sequel. Bumped for every non-patch level
5
5
  # release, generally around once a month.
6
- MINOR = 24
6
+ MINOR = 25
7
7
  # The tiny version of Sequel. Usually 0, only bumped for bugfix
8
8
  # releases that fix regressions from previous versions.
9
- TINY = 1
9
+ TINY = 0
10
10
 
11
11
  # The version of Sequel you are using, as a string (e.g. "2.11.0")
12
12
  VERSION = [MAJOR, MINOR, TINY].join('.')
@@ -998,6 +998,13 @@ if MYSQL_DB.adapter_scheme == :mysql or MYSQL_DB.adapter_scheme == :jdbc
998
998
  @d.row_proc = proc{|r| r.keys.each{|k| r[k] *= 2 if r[k].is_a?(Integer)}; r}
999
999
  @d.call_sproc(:select, :test_sproc, 3, 4).should == [{:id=>nil, :value=>2, :b=>6, :d => 8}]
1000
1000
  end
1001
+
1002
+ specify "should deal with nil values" do
1003
+ MYSQL_DB.execute_ddl('CREATE PROCEDURE test_sproc(i INTEGER, v INTEGER) BEGIN INSERT INTO items VALUES (i, v); END')
1004
+ MYSQL_DB[:items].delete
1005
+ MYSQL_DB.call_sproc(:test_sproc, :args=>[1, nil])
1006
+ MYSQL_DB[:items].all.should == [{:id=>1, :value=>nil}]
1007
+ end
1001
1008
  end
1002
1009
  end
1003
1010
 
@@ -478,233 +478,6 @@ describe "Database#test_connection" do
478
478
  end
479
479
  end
480
480
 
481
- class DummyDataset < Sequel::Dataset
482
- def first
483
- raise if @opts[:from] == [:a]
484
- true
485
- end
486
- end
487
-
488
- class DummyDatabase < Sequel::Database
489
- attr_reader :sqls
490
-
491
- def execute(sql, opts={})
492
- @sqls ||= []
493
- @sqls << sql
494
- end
495
-
496
- def transaction; yield; end
497
-
498
- def dataset
499
- DummyDataset.new(self)
500
- end
501
- end
502
-
503
- describe "Database#create_table" do
504
- before do
505
- @db = DummyDatabase.new
506
- end
507
-
508
- specify "should construct proper SQL" do
509
- @db.create_table :test do
510
- primary_key :id, :integer, :null => false
511
- column :name, :text
512
- index :name, :unique => true
513
- end
514
- @db.sqls.should == [
515
- 'CREATE TABLE test (id integer NOT NULL PRIMARY KEY AUTOINCREMENT, name text)',
516
- 'CREATE UNIQUE INDEX test_name_index ON test (name)'
517
- ]
518
- end
519
-
520
- specify "should create a temporary table" do
521
- @db.create_table :test_tmp, :temp => true do
522
- primary_key :id, :integer, :null => false
523
- column :name, :text
524
- index :name, :unique => true
525
- end
526
-
527
- @db.sqls.should == [
528
- 'CREATE TEMPORARY TABLE test_tmp (id integer NOT NULL PRIMARY KEY AUTOINCREMENT, name text)',
529
- 'CREATE UNIQUE INDEX test_tmp_name_index ON test_tmp (name)'
530
- ]
531
- end
532
-
533
- specify "should not use default schema when creating a temporary table" do
534
- @db.default_schema = :foo
535
- @db.create_table :test_tmp, :temp => true do
536
- column :name, :text
537
- end
538
- @db.sqls.should == ['CREATE TEMPORARY TABLE test_tmp (name text)']
539
- end
540
- end
541
-
542
- describe "Database#alter_table" do
543
- before do
544
- @db = DummyDatabase.new
545
- end
546
-
547
- specify "should construct proper SQL" do
548
- @db.alter_table :xyz do
549
- add_column :aaa, :text, :null => false, :unique => true
550
- drop_column :bbb
551
- rename_column :ccc, :ddd
552
- set_column_type :eee, :integer
553
- set_column_default :hhh, 'abcd'
554
-
555
- add_index :fff, :unique => true
556
- drop_index :ggg
557
- end
558
-
559
- @db.sqls.should == [
560
- 'ALTER TABLE xyz ADD COLUMN aaa text NOT NULL UNIQUE',
561
- 'ALTER TABLE xyz DROP COLUMN bbb',
562
- 'ALTER TABLE xyz RENAME COLUMN ccc TO ddd',
563
- 'ALTER TABLE xyz ALTER COLUMN eee TYPE integer',
564
- "ALTER TABLE xyz ALTER COLUMN hhh SET DEFAULT 'abcd'",
565
-
566
- 'CREATE UNIQUE INDEX xyz_fff_index ON xyz (fff)',
567
- 'DROP INDEX xyz_ggg_index'
568
- ]
569
- end
570
- end
571
-
572
- describe "Database#add_column" do
573
- before do
574
- @db = DummyDatabase.new
575
- end
576
-
577
- specify "should construct proper SQL" do
578
- @db.add_column :test, :name, :text, :unique => true
579
- @db.sqls.should == [
580
- 'ALTER TABLE test ADD COLUMN name text UNIQUE'
581
- ]
582
- end
583
- end
584
-
585
- describe "Database#drop_column" do
586
- before do
587
- @db = DummyDatabase.new
588
- end
589
-
590
- specify "should construct proper SQL" do
591
- @db.drop_column :test, :name
592
- @db.sqls.should == [
593
- 'ALTER TABLE test DROP COLUMN name'
594
- ]
595
- end
596
- end
597
-
598
- describe "Database#rename_column" do
599
- before do
600
- @db = DummyDatabase.new
601
- end
602
-
603
- specify "should construct proper SQL" do
604
- @db.rename_column :test, :abc, :def
605
- @db.sqls.should == [
606
- 'ALTER TABLE test RENAME COLUMN abc TO def'
607
- ]
608
- end
609
- end
610
-
611
- describe "Database#set_column_type" do
612
- before do
613
- @db = DummyDatabase.new
614
- end
615
-
616
- specify "should construct proper SQL" do
617
- @db.set_column_type :test, :name, :integer
618
- @db.sqls.should == [
619
- 'ALTER TABLE test ALTER COLUMN name TYPE integer'
620
- ]
621
- end
622
- end
623
-
624
- describe "Database#set_column_default" do
625
- before do
626
- @db = DummyDatabase.new
627
- end
628
-
629
- specify "should construct proper SQL" do
630
- @db.set_column_default :test, :name, 'zyx'
631
- @db.sqls.should == [
632
- "ALTER TABLE test ALTER COLUMN name SET DEFAULT 'zyx'"
633
- ]
634
- end
635
- end
636
-
637
- describe "Database#add_index" do
638
- before do
639
- @db = DummyDatabase.new
640
- end
641
-
642
- specify "should construct proper SQL" do
643
- @db.add_index :test, :name, :unique => true
644
- @db.sqls.should == [
645
- 'CREATE UNIQUE INDEX test_name_index ON test (name)'
646
- ]
647
- end
648
-
649
- specify "should accept multiple columns" do
650
- @db.add_index :test, [:one, :two]
651
- @db.sqls.should == [
652
- 'CREATE INDEX test_one_two_index ON test (one, two)'
653
- ]
654
- end
655
- end
656
-
657
- describe "Database#drop_index" do
658
- before do
659
- @db = DummyDatabase.new
660
- end
661
-
662
- specify "should construct proper SQL" do
663
- @db.drop_index :test, :name
664
- @db.sqls.should == [
665
- 'DROP INDEX test_name_index'
666
- ]
667
- end
668
-
669
- end
670
-
671
- class Dummy2Database < Sequel::Database
672
- attr_reader :sql
673
- def execute(sql); @sql = sql; end
674
- def transaction; yield; end
675
- end
676
-
677
- describe "Database#drop_table" do
678
- before do
679
- @db = DummyDatabase.new
680
- end
681
-
682
- specify "should construct proper SQL" do
683
- @db.drop_table :test
684
- @db.sqls.should == ['DROP TABLE test']
685
- end
686
-
687
- specify "should accept multiple table names" do
688
- @db.drop_table :a, :bb, :ccc
689
- @db.sqls.should == [
690
- 'DROP TABLE a',
691
- 'DROP TABLE bb',
692
- 'DROP TABLE ccc'
693
- ]
694
- end
695
- end
696
-
697
- describe "Database#rename_table" do
698
- before do
699
- @db = DummyDatabase.new
700
- end
701
-
702
- specify "should construct proper SQL" do
703
- @db.rename_table :abc, :xyz
704
- @db.sqls.should == ['ALTER TABLE abc RENAME TO xyz']
705
- end
706
- end
707
-
708
481
  describe "Database#table_exists?" do
709
482
  specify "should try to select the first record from the table's dataset" do
710
483
  db2 = DummyDatabase.new
@@ -1282,74 +1055,6 @@ describe "Database#[]" do
1282
1055
  end
1283
1056
  end
1284
1057
 
1285
- describe "Database#create_view" do
1286
- before do
1287
- @db = DummyDatabase.new
1288
- end
1289
-
1290
- specify "should construct proper SQL with raw SQL" do
1291
- @db.create_view :test, "SELECT * FROM xyz"
1292
- @db.sqls.should == ['CREATE VIEW test AS SELECT * FROM xyz']
1293
- @db.sqls.clear
1294
- @db.create_view :test.identifier, "SELECT * FROM xyz"
1295
- @db.sqls.should == ['CREATE VIEW test AS SELECT * FROM xyz']
1296
- end
1297
-
1298
- specify "should construct proper SQL with dataset" do
1299
- @db.create_view :test, @db[:items].select(:a, :b).order(:c)
1300
- @db.sqls.should == ['CREATE VIEW test AS SELECT a, b FROM items ORDER BY c']
1301
- @db.sqls.clear
1302
- @db.create_view :test.qualify(:sch), @db[:items].select(:a, :b).order(:c)
1303
- @db.sqls.should == ['CREATE VIEW sch.test AS SELECT a, b FROM items ORDER BY c']
1304
- end
1305
- end
1306
-
1307
- describe "Database#create_or_replace_view" do
1308
- before do
1309
- @db = DummyDatabase.new
1310
- end
1311
-
1312
- specify "should construct proper SQL with raw SQL" do
1313
- @db.create_or_replace_view :test, "SELECT * FROM xyz"
1314
- @db.sqls.should == ['CREATE OR REPLACE VIEW test AS SELECT * FROM xyz']
1315
- @db.sqls.clear
1316
- @db.create_or_replace_view :sch__test, "SELECT * FROM xyz"
1317
- @db.sqls.should == ['CREATE OR REPLACE VIEW sch.test AS SELECT * FROM xyz']
1318
- end
1319
-
1320
- specify "should construct proper SQL with dataset" do
1321
- @db.create_or_replace_view :test, @db[:items].select(:a, :b).order(:c)
1322
- @db.sqls.should == ['CREATE OR REPLACE VIEW test AS SELECT a, b FROM items ORDER BY c']
1323
- @db.sqls.clear
1324
- @db.create_or_replace_view :test.identifier, @db[:items].select(:a, :b).order(:c)
1325
- @db.sqls.should == ['CREATE OR REPLACE VIEW test AS SELECT a, b FROM items ORDER BY c']
1326
- end
1327
- end
1328
-
1329
- describe "Database#drop_view" do
1330
- before do
1331
- @db = DummyDatabase.new
1332
- end
1333
-
1334
- specify "should construct proper SQL" do
1335
- @db.drop_view :test
1336
- @db.drop_view :test.identifier
1337
- @db.drop_view :sch__test
1338
- @db.drop_view :test.qualify(:sch)
1339
- @db.sqls.should == ['DROP VIEW test', 'DROP VIEW test', 'DROP VIEW sch.test', 'DROP VIEW sch.test']
1340
- end
1341
- end
1342
-
1343
- describe "Database#alter_table_sql" do
1344
- before do
1345
- @db = DummyDatabase.new
1346
- end
1347
-
1348
- specify "should raise error for an invalid op" do
1349
- proc {@db.send(:alter_table_sql, :mau, :op => :blah)}.should raise_error(Sequel::Error)
1350
- end
1351
- end
1352
-
1353
1058
  describe "Database#inspect" do
1354
1059
  before do
1355
1060
  @db = DummyDatabase.new