sequel 3.24.0 → 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.
- data/CHANGELOG +32 -0
- data/doc/association_basics.rdoc +4 -4
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/migration.rdoc +6 -5
- data/doc/opening_databases.rdoc +8 -5
- data/doc/release_notes/3.25.0.txt +88 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +6 -0
- data/lib/sequel/adapters/jdbc.rb +2 -2
- data/lib/sequel/adapters/shared/postgres.rb +0 -5
- data/lib/sequel/adapters/tinytds.rb +1 -2
- data/lib/sequel/database/schema_generator.rb +6 -4
- data/lib/sequel/database/schema_methods.rb +18 -7
- data/lib/sequel/dataset/misc.rb +0 -9
- data/lib/sequel/dataset/query.rb +80 -21
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/extensions/migration.rb +1 -1
- data/lib/sequel/model/base.rb +15 -6
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/plugins/association_pks.rb +16 -0
- data/lib/sequel/plugins/update_primary_key.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mysql_spec.rb +7 -0
- data/spec/core/database_spec.rb +0 -295
- data/spec/core/dataset_spec.rb +70 -1
- data/spec/core/expression_filters_spec.rb +39 -0
- data/spec/core/schema_spec.rb +304 -0
- data/spec/core/spec_helper.rb +29 -0
- data/spec/extensions/association_pks_spec.rb +31 -0
- data/spec/extensions/schema_spec.rb +12 -20
- data/spec/integration/dataset_test.rb +17 -0
- data/spec/integration/prepared_statement_test.rb +15 -0
- data/spec/integration/schema_test.rb +9 -0
- data/spec/model/model_spec.rb +60 -0
- data/spec/model/plugins_spec.rb +17 -0
- data/spec/model/validations_spec.rb +11 -0
- metadata +6 -4
data/lib/sequel/model/base.rb
CHANGED
|
@@ -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
|
|
330
|
-
extend(m::ClassMethods)if
|
|
331
|
-
if
|
|
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
|
|
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)
|
data/lib/sequel/model/errors.rb
CHANGED
|
@@ -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
|
|
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
|
data/lib/sequel/version.rb
CHANGED
|
@@ -3,7 +3,7 @@ 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 =
|
|
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
9
|
TINY = 0
|
data/spec/adapters/mysql_spec.rb
CHANGED
|
@@ -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
|
|
data/spec/core/database_spec.rb
CHANGED
|
@@ -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
|
data/spec/core/dataset_spec.rb
CHANGED
|
@@ -759,6 +759,11 @@ describe "Dataset#exclude" do
|
|
|
759
759
|
"SELECT * FROM test WHERE (region != 'Asia')"
|
|
760
760
|
end
|
|
761
761
|
|
|
762
|
+
specify "should affect the having clause if having clause is already used" do
|
|
763
|
+
@dataset.group_and_count(:name).having{count > 2}.exclude{count > 5}.sql.should ==
|
|
764
|
+
"SELECT name, count(*) AS count FROM test GROUP BY name HAVING ((count > 2) AND (count <= 5))"
|
|
765
|
+
end
|
|
766
|
+
|
|
762
767
|
specify "should take multiple conditions as a hash and express the logic correctly in SQL" do
|
|
763
768
|
@dataset.exclude(:region => 'Asia', :name => 'Japan').select_sql.
|
|
764
769
|
should match(Regexp.union(/WHERE \(\(region != 'Asia'\) OR \(name != 'Japan'\)\)/,
|
|
@@ -793,6 +798,28 @@ describe "Dataset#exclude" do
|
|
|
793
798
|
end
|
|
794
799
|
end
|
|
795
800
|
|
|
801
|
+
describe "Dataset#exclude_where" do
|
|
802
|
+
before do
|
|
803
|
+
@dataset = Sequel::Dataset.new(nil).from(:test)
|
|
804
|
+
end
|
|
805
|
+
|
|
806
|
+
specify "should correctly negate the expression and add it to the where clause" do
|
|
807
|
+
@dataset.exclude_where(:region=>'Asia').sql.should == "SELECT * FROM test WHERE (region != 'Asia')"
|
|
808
|
+
@dataset.exclude_where(:region=>'Asia').exclude_where(:region=>'NA').sql.should == "SELECT * FROM test WHERE ((region != 'Asia') AND (region != 'NA'))"
|
|
809
|
+
end
|
|
810
|
+
|
|
811
|
+
specify "should affect the where clause even if having clause is already used" do
|
|
812
|
+
@dataset.group_and_count(:name).having{count > 2}.exclude_where(:region=>'Asia').sql.should ==
|
|
813
|
+
"SELECT name, count(*) AS count FROM test WHERE (region != 'Asia') GROUP BY name HAVING (count > 2)"
|
|
814
|
+
end
|
|
815
|
+
end
|
|
816
|
+
|
|
817
|
+
describe "Dataset#exclude_having" do
|
|
818
|
+
specify "should correctly negate the expression and add it to the having clause" do
|
|
819
|
+
Sequel::Dataset.new(nil).from(:test).exclude_having{count > 2}.exclude_having{count < 0}.sql.should == "SELECT * FROM test HAVING ((count <= 2) AND (count >= 0))"
|
|
820
|
+
end
|
|
821
|
+
end
|
|
822
|
+
|
|
796
823
|
describe "Dataset#invert" do
|
|
797
824
|
before do
|
|
798
825
|
@d = Sequel::Dataset.new(nil).from(:test)
|
|
@@ -897,7 +924,7 @@ describe "Dataset#group_by" do
|
|
|
897
924
|
"SELECT * FROM test GROUP BY (type_id IS NULL)"
|
|
898
925
|
end
|
|
899
926
|
|
|
900
|
-
specify "should ungroup when passed nil
|
|
927
|
+
specify "should ungroup when passed nil or no arguments" do
|
|
901
928
|
@dataset.group_by.select_sql.should ==
|
|
902
929
|
"SELECT * FROM test"
|
|
903
930
|
@dataset.group_by(nil).select_sql.should ==
|
|
@@ -915,6 +942,13 @@ describe "Dataset#group_by" do
|
|
|
915
942
|
@dataset.group(:type_id=>nil).select_sql.should ==
|
|
916
943
|
"SELECT * FROM test GROUP BY (type_id IS NULL)"
|
|
917
944
|
end
|
|
945
|
+
|
|
946
|
+
specify "should take a virtual row block" do
|
|
947
|
+
@dataset.group{type_id > 1}.sql.should == "SELECT * FROM test GROUP BY (type_id > 1)"
|
|
948
|
+
@dataset.group_by{type_id > 1}.sql.should == "SELECT * FROM test GROUP BY (type_id > 1)"
|
|
949
|
+
@dataset.group{[type_id > 1, type_id < 2]}.sql.should == "SELECT * FROM test GROUP BY (type_id > 1), (type_id < 2)"
|
|
950
|
+
@dataset.group(:foo){type_id > 1}.sql.should == "SELECT * FROM test GROUP BY foo, (type_id > 1)"
|
|
951
|
+
end
|
|
918
952
|
end
|
|
919
953
|
|
|
920
954
|
describe "Dataset#as" do
|
|
@@ -1219,6 +1253,27 @@ describe "Dataset#select" do
|
|
|
1219
1253
|
end
|
|
1220
1254
|
end
|
|
1221
1255
|
|
|
1256
|
+
describe "Dataset#select_group" do
|
|
1257
|
+
before do
|
|
1258
|
+
@d = Sequel::Dataset.new(nil).from(:test)
|
|
1259
|
+
end
|
|
1260
|
+
|
|
1261
|
+
specify "should set both SELECT and GROUP" do
|
|
1262
|
+
@d.select_group(:name).sql.should == 'SELECT name FROM test GROUP BY name'
|
|
1263
|
+
@d.select_group(:a, :b__c, :d___e).sql.should == 'SELECT a, b.c, d AS e FROM test GROUP BY a, b.c, d'
|
|
1264
|
+
end
|
|
1265
|
+
|
|
1266
|
+
specify "should remove from both SELECT and GROUP if no arguments" do
|
|
1267
|
+
@d.select_group(:name).select_group.sql.should == 'SELECT * FROM test'
|
|
1268
|
+
end
|
|
1269
|
+
|
|
1270
|
+
specify "should accept virtual row blocks" do
|
|
1271
|
+
@d.select_group{name}.sql.should == 'SELECT name FROM test GROUP BY name'
|
|
1272
|
+
@d.select_group{[name, f(v).as(a)]}.sql.should == 'SELECT name, f(v) AS a FROM test GROUP BY name, f(v)'
|
|
1273
|
+
@d.select_group(:name){f(v).as(a)}.sql.should == 'SELECT name, f(v) AS a FROM test GROUP BY name, f(v)'
|
|
1274
|
+
end
|
|
1275
|
+
end
|
|
1276
|
+
|
|
1222
1277
|
describe "Dataset#select_all" do
|
|
1223
1278
|
before do
|
|
1224
1279
|
@d = Sequel::Dataset.new(nil).from(:test)
|
|
@@ -1231,6 +1286,14 @@ describe "Dataset#select_all" do
|
|
|
1231
1286
|
specify "should overrun the previous select option" do
|
|
1232
1287
|
@d.select!(:a, :b, :c).select_all.sql.should == 'SELECT * FROM test'
|
|
1233
1288
|
end
|
|
1289
|
+
|
|
1290
|
+
specify "should select all columns in a table if given an argument" do
|
|
1291
|
+
@d.select_all(:test).sql.should == 'SELECT test.* FROM test'
|
|
1292
|
+
end
|
|
1293
|
+
|
|
1294
|
+
specify "should select all columns all tables if given a multiple arguments" do
|
|
1295
|
+
@d.select_all(:test, :foo).sql.should == 'SELECT test.*, foo.* FROM test'
|
|
1296
|
+
end
|
|
1234
1297
|
end
|
|
1235
1298
|
|
|
1236
1299
|
describe "Dataset#select_more" do
|
|
@@ -1774,6 +1837,12 @@ describe "Dataset#group_and_count" do
|
|
|
1774
1837
|
@ds.group_and_count(:name.identifier.as(:n)).sql.should ==
|
|
1775
1838
|
"SELECT name AS n, count(*) AS count FROM test GROUP BY name"
|
|
1776
1839
|
end
|
|
1840
|
+
|
|
1841
|
+
specify "should take a virtual row block" do
|
|
1842
|
+
@ds.group_and_count{(type_id > 1).as(t)}.sql.should == "SELECT (type_id > 1) AS t, count(*) AS count FROM test GROUP BY (type_id > 1)"
|
|
1843
|
+
@ds.group_and_count{[(type_id > 1).as(t), type_id < 2]}.sql.should == "SELECT (type_id > 1) AS t, (type_id < 2), count(*) AS count FROM test GROUP BY (type_id > 1), (type_id < 2)"
|
|
1844
|
+
@ds.group_and_count(:foo){type_id > 1}.sql.should == "SELECT foo, (type_id > 1), count(*) AS count FROM test GROUP BY foo, (type_id > 1)"
|
|
1845
|
+
end
|
|
1777
1846
|
end
|
|
1778
1847
|
|
|
1779
1848
|
describe "Dataset#empty?" do
|
|
@@ -452,6 +452,45 @@ describe "Blockless Ruby Filters" do
|
|
|
452
452
|
e2 = ~:comment.like('%:hidden:%')
|
|
453
453
|
e1.should == e2
|
|
454
454
|
end
|
|
455
|
+
|
|
456
|
+
it "should support expression filter methods on Datasets" do
|
|
457
|
+
d = @d.select(:a)
|
|
458
|
+
|
|
459
|
+
@d.lit(d + 1).should == '((SELECT a FROM items) + 1)'
|
|
460
|
+
@d.lit(d - 1).should == '((SELECT a FROM items) - 1)'
|
|
461
|
+
@d.lit(d * 1).should == '((SELECT a FROM items) * 1)'
|
|
462
|
+
@d.lit(d / 1).should == '((SELECT a FROM items) / 1)'
|
|
463
|
+
|
|
464
|
+
@d.lit(d => 1).should == '((SELECT a FROM items) = 1)'
|
|
465
|
+
@d.lit(~{d => 1}).should == '((SELECT a FROM items) != 1)'
|
|
466
|
+
@d.lit(d > 1).should == '((SELECT a FROM items) > 1)'
|
|
467
|
+
@d.lit(d < 1).should == '((SELECT a FROM items) < 1)'
|
|
468
|
+
@d.lit(d >= 1).should == '((SELECT a FROM items) >= 1)'
|
|
469
|
+
@d.lit(d <= 1).should == '((SELECT a FROM items) <= 1)'
|
|
470
|
+
|
|
471
|
+
@d.lit(d.as(:b)).should == '(SELECT a FROM items) AS b'
|
|
472
|
+
|
|
473
|
+
@d.lit(d & :b).should == '((SELECT a FROM items) AND b)'
|
|
474
|
+
@d.lit(d | :b).should == '((SELECT a FROM items) OR b)'
|
|
475
|
+
@d.lit(~d).should == 'NOT (SELECT a FROM items)'
|
|
476
|
+
|
|
477
|
+
@d.lit(d.cast(Integer)).should == 'CAST((SELECT a FROM items) AS integer)'
|
|
478
|
+
@d.lit(d.cast_numeric).should == 'CAST((SELECT a FROM items) AS integer)'
|
|
479
|
+
@d.lit(d.cast_string).should == 'CAST((SELECT a FROM items) AS varchar(255))'
|
|
480
|
+
@d.lit(d.cast_numeric << :b).should == '(CAST((SELECT a FROM items) AS integer) << b)'
|
|
481
|
+
@d.lit(d.cast_string + :b).should == '(CAST((SELECT a FROM items) AS varchar(255)) || b)'
|
|
482
|
+
|
|
483
|
+
@d.lit(d.extract(:year)).should == 'extract(year FROM (SELECT a FROM items))'
|
|
484
|
+
@d.lit(d.sql_boolean & :b).should == '((SELECT a FROM items) AND b)'
|
|
485
|
+
@d.lit(d.sql_number << :b).should == '((SELECT a FROM items) << b)'
|
|
486
|
+
@d.lit(d.sql_string + :b).should == '((SELECT a FROM items) || b)'
|
|
487
|
+
|
|
488
|
+
@d.lit(d.asc).should == '(SELECT a FROM items) ASC'
|
|
489
|
+
@d.lit(d.desc).should == '(SELECT a FROM items) DESC'
|
|
490
|
+
|
|
491
|
+
@d.lit(d.like(:b)).should == '((SELECT a FROM items) LIKE b)'
|
|
492
|
+
@d.lit(d.ilike(:b)).should == '((SELECT a FROM items) ILIKE b)'
|
|
493
|
+
end
|
|
455
494
|
|
|
456
495
|
if RUBY_VERSION < '1.9.0'
|
|
457
496
|
it "should not allow inequality operations on true, false, or nil" do
|