sequel 3.24.1 → 3.25.0

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.
@@ -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