sequel 3.37.0 → 3.38.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +56 -0
- data/README.rdoc +82 -58
- data/Rakefile +6 -5
- data/bin/sequel +1 -1
- data/doc/active_record.rdoc +67 -52
- data/doc/advanced_associations.rdoc +33 -48
- data/doc/association_basics.rdoc +41 -51
- data/doc/cheat_sheet.rdoc +21 -21
- data/doc/core_extensions.rdoc +374 -0
- data/doc/dataset_basics.rdoc +5 -5
- data/doc/dataset_filtering.rdoc +47 -43
- data/doc/mass_assignment.rdoc +1 -1
- data/doc/migration.rdoc +4 -5
- data/doc/model_hooks.rdoc +3 -3
- data/doc/object_model.rdoc +31 -25
- data/doc/opening_databases.rdoc +19 -5
- data/doc/prepared_statements.rdoc +2 -2
- data/doc/querying.rdoc +109 -52
- data/doc/reflection.rdoc +6 -6
- data/doc/release_notes/3.38.0.txt +234 -0
- data/doc/schema_modification.rdoc +22 -13
- data/doc/sharding.rdoc +8 -9
- data/doc/sql.rdoc +154 -112
- data/doc/testing.rdoc +47 -7
- data/doc/thread_safety.rdoc +1 -1
- data/doc/transactions.rdoc +1 -1
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +29 -43
- data/lib/sequel/adapters/do/postgres.rb +1 -4
- data/lib/sequel/adapters/jdbc.rb +14 -3
- data/lib/sequel/adapters/jdbc/db2.rb +9 -0
- data/lib/sequel/adapters/jdbc/derby.rb +41 -4
- data/lib/sequel/adapters/jdbc/jtds.rb +11 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +3 -6
- data/lib/sequel/adapters/mock.rb +10 -4
- data/lib/sequel/adapters/postgres.rb +1 -28
- data/lib/sequel/adapters/shared/mssql.rb +23 -13
- data/lib/sequel/adapters/shared/postgres.rb +46 -0
- data/lib/sequel/adapters/swift.rb +21 -13
- data/lib/sequel/adapters/swift/mysql.rb +1 -0
- data/lib/sequel/adapters/swift/postgres.rb +4 -5
- data/lib/sequel/adapters/swift/sqlite.rb +2 -1
- data/lib/sequel/adapters/tinytds.rb +14 -2
- data/lib/sequel/adapters/utils/pg_types.rb +5 -0
- data/lib/sequel/core.rb +29 -17
- data/lib/sequel/database/query.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +3 -0
- data/lib/sequel/dataset/actions.rb +5 -6
- data/lib/sequel/dataset/query.rb +7 -7
- data/lib/sequel/dataset/sql.rb +5 -18
- data/lib/sequel/extensions/core_extensions.rb +8 -12
- data/lib/sequel/extensions/pg_array.rb +59 -33
- data/lib/sequel/extensions/pg_array_ops.rb +32 -4
- data/lib/sequel/extensions/pg_auto_parameterize.rb +1 -1
- data/lib/sequel/extensions/pg_hstore.rb +32 -17
- data/lib/sequel/extensions/pg_hstore_ops.rb +32 -3
- data/lib/sequel/extensions/pg_inet.rb +1 -2
- data/lib/sequel/extensions/pg_interval.rb +0 -1
- data/lib/sequel/extensions/pg_json.rb +41 -23
- data/lib/sequel/extensions/pg_range.rb +36 -11
- data/lib/sequel/extensions/pg_range_ops.rb +32 -4
- data/lib/sequel/extensions/pg_row.rb +572 -0
- data/lib/sequel/extensions/pg_row_ops.rb +164 -0
- data/lib/sequel/extensions/query.rb +3 -3
- data/lib/sequel/extensions/schema_dumper.rb +7 -8
- data/lib/sequel/extensions/select_remove.rb +1 -1
- data/lib/sequel/model/base.rb +1 -0
- data/lib/sequel/no_core_ext.rb +1 -1
- data/lib/sequel/plugins/pg_row.rb +121 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
- data/lib/sequel/plugins/validation_helpers.rb +31 -0
- data/lib/sequel/sql.rb +64 -44
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +37 -12
- data/spec/adapters/mysql_spec.rb +39 -75
- data/spec/adapters/oracle_spec.rb +11 -11
- data/spec/adapters/postgres_spec.rb +414 -237
- data/spec/adapters/spec_helper.rb +1 -1
- data/spec/adapters/sqlite_spec.rb +14 -14
- data/spec/core/database_spec.rb +6 -6
- data/spec/core/dataset_spec.rb +169 -205
- data/spec/core/expression_filters_spec.rb +182 -295
- data/spec/core/object_graph_spec.rb +6 -6
- data/spec/core/schema_spec.rb +14 -14
- data/spec/core/spec_helper.rb +1 -0
- data/spec/{extensions/core_extensions_spec.rb → core_extensions_spec.rb} +208 -14
- data/spec/extensions/columns_introspection_spec.rb +5 -5
- data/spec/extensions/hook_class_methods_spec.rb +28 -36
- data/spec/extensions/many_through_many_spec.rb +4 -4
- data/spec/extensions/pg_array_ops_spec.rb +15 -7
- data/spec/extensions/pg_array_spec.rb +81 -48
- data/spec/extensions/pg_auto_parameterize_spec.rb +2 -2
- data/spec/extensions/pg_hstore_ops_spec.rb +13 -9
- data/spec/extensions/pg_hstore_spec.rb +66 -65
- data/spec/extensions/pg_inet_spec.rb +2 -4
- data/spec/extensions/pg_interval_spec.rb +2 -3
- data/spec/extensions/pg_json_spec.rb +20 -18
- data/spec/extensions/pg_range_ops_spec.rb +11 -4
- data/spec/extensions/pg_range_spec.rb +30 -7
- data/spec/extensions/pg_row_ops_spec.rb +48 -0
- data/spec/extensions/pg_row_plugin_spec.rb +45 -0
- data/spec/extensions/pg_row_spec.rb +323 -0
- data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
- data/spec/extensions/query_literals_spec.rb +11 -11
- data/spec/extensions/query_spec.rb +3 -3
- data/spec/extensions/schema_dumper_spec.rb +20 -4
- data/spec/extensions/schema_spec.rb +18 -41
- data/spec/extensions/select_remove_spec.rb +4 -4
- data/spec/extensions/spec_helper.rb +4 -8
- data/spec/extensions/to_dot_spec.rb +5 -5
- data/spec/extensions/validation_class_methods_spec.rb +28 -16
- data/spec/integration/associations_test.rb +20 -20
- data/spec/integration/dataset_test.rb +98 -98
- data/spec/integration/eager_loader_test.rb +13 -27
- data/spec/integration/plugin_test.rb +5 -5
- data/spec/integration/prepared_statement_test.rb +22 -13
- data/spec/integration/schema_test.rb +28 -18
- data/spec/integration/spec_helper.rb +1 -1
- data/spec/integration/timezone_test.rb +2 -2
- data/spec/integration/type_test.rb +15 -6
- data/spec/model/association_reflection_spec.rb +1 -1
- data/spec/model/associations_spec.rb +4 -4
- data/spec/model/base_spec.rb +5 -5
- data/spec/model/eager_loading_spec.rb +15 -15
- data/spec/model/model_spec.rb +32 -32
- data/spec/model/record_spec.rb +16 -0
- data/spec/model/spec_helper.rb +2 -6
- data/spec/model/validations_spec.rb +1 -1
- metadata +16 -4
data/lib/sequel/sql.rb
CHANGED
@@ -217,7 +217,7 @@ module Sequel
|
|
217
217
|
module AliasMethods
|
218
218
|
# Create an SQL alias (+AliasedExpression+) of the receiving column or expression to the given alias.
|
219
219
|
#
|
220
|
-
# :
|
220
|
+
# Sequel.function(:func).as(:alias) # func() AS "alias"
|
221
221
|
def as(aliaz)
|
222
222
|
AliasedExpression.new(self, aliaz)
|
223
223
|
end
|
@@ -389,6 +389,20 @@ module Sequel
|
|
389
389
|
end
|
390
390
|
|
391
391
|
case arg
|
392
|
+
when Symbol
|
393
|
+
t, c, a = Sequel.split_symbol(arg)
|
394
|
+
|
395
|
+
arg = if t
|
396
|
+
SQL::QualifiedIdentifier.new(t, c)
|
397
|
+
else
|
398
|
+
SQL::Identifier.new(c)
|
399
|
+
end
|
400
|
+
|
401
|
+
if a
|
402
|
+
arg = SQL::AliasedExpression.new(arg, a)
|
403
|
+
end
|
404
|
+
|
405
|
+
arg
|
392
406
|
when SQL::Expression, LiteralString, SQL::Blob
|
393
407
|
arg
|
394
408
|
when Hash
|
@@ -573,8 +587,8 @@ module Sequel
|
|
573
587
|
# Cast the reciever to the given SQL type. You can specify a ruby class as a type,
|
574
588
|
# and it is handled similarly to using a database independent type in the schema methods.
|
575
589
|
#
|
576
|
-
# :
|
577
|
-
# :
|
590
|
+
# Sequel.function(:func).cast(:integer) # CAST(func() AS integer)
|
591
|
+
# Sequel.function(:func).cast(String) # CAST(func() AS varchar(255))
|
578
592
|
def cast(sql_type)
|
579
593
|
Cast.new(self, sql_type)
|
580
594
|
end
|
@@ -583,8 +597,8 @@ module Sequel
|
|
583
597
|
# and return the result as a +NumericExpression+, so you can use the bitwise operators
|
584
598
|
# on the result.
|
585
599
|
#
|
586
|
-
# :
|
587
|
-
# :
|
600
|
+
# Sequel.function(:func).cast_numeric # CAST(func() AS integer)
|
601
|
+
# Sequel.function(:func).cast_numeric(Float) # CAST(func() AS double precision)
|
588
602
|
def cast_numeric(sql_type = nil)
|
589
603
|
cast(sql_type || Integer).sql_number
|
590
604
|
end
|
@@ -593,13 +607,13 @@ module Sequel
|
|
593
607
|
# and return the result as a +StringExpression+, so you can use +
|
594
608
|
# directly on the result for SQL string concatenation.
|
595
609
|
#
|
596
|
-
# :
|
597
|
-
# :
|
610
|
+
# Sequel.function(:func).cast_string # CAST(func() AS varchar(255))
|
611
|
+
# Sequel.function(:func).cast_string(:text) # CAST(func() AS text)
|
598
612
|
def cast_string(sql_type = nil)
|
599
613
|
cast(sql_type || String).sql_string
|
600
614
|
end
|
601
615
|
end
|
602
|
-
|
616
|
+
|
603
617
|
# Adds methods that allow you to treat an object as an instance of a specific
|
604
618
|
# +ComplexExpression+ subclass. This is useful if another library
|
605
619
|
# overrides the methods defined by Sequel.
|
@@ -614,7 +628,7 @@ module Sequel
|
|
614
628
|
#
|
615
629
|
# :price.sql_number/10 > 100
|
616
630
|
module ComplexExpressionMethods
|
617
|
-
# Extract a
|
631
|
+
# Extract a datetime part (e.g. year, month) from self:
|
618
632
|
#
|
619
633
|
# :date.extract(:year) # extract(year FROM "date")
|
620
634
|
#
|
@@ -646,25 +660,13 @@ module Sequel
|
|
646
660
|
end
|
647
661
|
end
|
648
662
|
|
649
|
-
# Includes an +identifier+ method that returns <tt>Identifier</tt>s.
|
650
|
-
module IdentifierMethods
|
651
|
-
# Return self wrapped as an <tt>SQL::Identifier</tt>.
|
652
|
-
#
|
653
|
-
# :a__b # "a"."b"
|
654
|
-
# :a__b.identifier # "a__b"
|
655
|
-
def identifier
|
656
|
-
Identifier.new(self)
|
657
|
-
end
|
658
|
-
end
|
659
|
-
|
660
663
|
# This module includes the inequality methods (>, <, >=, <=) that are defined on objects that can be
|
661
|
-
# used in a numeric or string context in SQL
|
662
|
-
# <tt>SQL::GenericExpression</tt>).
|
664
|
+
# used in a numeric or string context in SQL.
|
663
665
|
#
|
664
|
-
# 'a'
|
665
|
-
# 'a'
|
666
|
-
# 'a'
|
667
|
-
# 'a'
|
666
|
+
# Sequel.lit('a') > :b # a > "b"
|
667
|
+
# Sequel.lit('a') < :b # a > "b"
|
668
|
+
# Sequel.lit('a') >= :b # a >= "b"
|
669
|
+
# Sequel.lit('a') <= :b # a <= "b"
|
668
670
|
module InequalityMethods
|
669
671
|
ComplexExpression::INEQUALITY_OPERATORS.each do |o|
|
670
672
|
module_eval("def #{o}(o) BooleanExpression.new(#{o.inspect}, self, o) end", __FILE__, __LINE__)
|
@@ -772,13 +774,25 @@ module Sequel
|
|
772
774
|
end
|
773
775
|
|
774
776
|
# Includes a +qualify+ method that created <tt>QualifiedIdentifier</tt>s, used for qualifying column
|
775
|
-
# names with a table or table names with a schema
|
777
|
+
# names with a table or table names with a schema, and the * method for returning all columns in
|
778
|
+
# the identifier if no arguments are given.
|
776
779
|
module QualifyingMethods
|
780
|
+
# If no arguments are given, return an SQL::ColumnAll:
|
781
|
+
#
|
782
|
+
# Sequel.expr(:a__b).* # a.b.*
|
783
|
+
def *(ce=(arg=false;nil))
|
784
|
+
if arg == false
|
785
|
+
Sequel::SQL::ColumnAll.new(self)
|
786
|
+
else
|
787
|
+
super(ce)
|
788
|
+
end
|
789
|
+
end
|
790
|
+
|
777
791
|
# Qualify the receiver with the given +qualifier+ (table for column/schema for table).
|
778
792
|
#
|
779
|
-
# :column.qualify(:table) # "table"."column"
|
780
|
-
# :table.qualify(:schema) # "schema"."table"
|
781
|
-
#
|
793
|
+
# Sequel.expr(:column).qualify(:table) # "table"."column"
|
794
|
+
# Sequel.expr(:table).qualify(:schema) # "schema"."table"
|
795
|
+
# Sequel.qualify(:table, :column).qualify(:schema) # "schema"."table"."column"
|
782
796
|
def qualify(qualifier)
|
783
797
|
QualifiedIdentifier.new(qualifier, self)
|
784
798
|
end
|
@@ -852,8 +866,16 @@ module Sequel
|
|
852
866
|
# stored as a blob type in the database. Sequel represents binary data as a Blob object because
|
853
867
|
# most database engines require binary data to be escaped differently than regular strings.
|
854
868
|
class Blob < ::String
|
855
|
-
|
856
|
-
|
869
|
+
include SQL::AliasMethods
|
870
|
+
include SQL::CastMethods
|
871
|
+
|
872
|
+
# Return a LiteralString with the same content if no args are given, otherwise
|
873
|
+
# return a SQL::PlaceholderLiteralString with the current string and the given args.
|
874
|
+
def lit(*args)
|
875
|
+
args.empty? ? LiteralString.new(self) : SQL::PlaceholderLiteralString.new(self, args)
|
876
|
+
end
|
877
|
+
|
878
|
+
# Returns +self+, since it is already a blob.
|
857
879
|
def to_sequel_blob
|
858
880
|
self
|
859
881
|
end
|
@@ -1570,20 +1592,18 @@ module Sequel
|
|
1570
1592
|
include SQL::NumericMethods
|
1571
1593
|
include SQL::StringMethods
|
1572
1594
|
include SQL::InequalityMethods
|
1573
|
-
|
1574
|
-
|
1575
|
-
# in String, so we don't need to include/define them here.
|
1576
|
-
unless Sequel.core_extensions?
|
1577
|
-
include Sequel::SQL::AliasMethods
|
1578
|
-
include Sequel::SQL::CastMethods
|
1595
|
+
include SQL::AliasMethods
|
1596
|
+
include SQL::CastMethods
|
1579
1597
|
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1598
|
+
# Return self if no args are given, otherwise return a SQL::PlaceholderLiteralString
|
1599
|
+
# with the current string and the given args.
|
1600
|
+
def lit(*args)
|
1601
|
+
args.empty? ? self : SQL::PlaceholderLiteralString.new(self, args)
|
1602
|
+
end
|
1583
1603
|
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1604
|
+
# Convert a literal string to a SQL::Blob.
|
1605
|
+
def to_sequel_blob
|
1606
|
+
SQL::Blob.new(self)
|
1587
1607
|
end
|
1588
1608
|
end
|
1589
1609
|
|
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 = 38
|
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/mssql_spec.rb
CHANGED
@@ -19,20 +19,20 @@ end
|
|
19
19
|
MSSQL_DB.loggers = [logger]
|
20
20
|
|
21
21
|
MSSQL_DB.create_table! :test do
|
22
|
-
|
23
|
-
|
22
|
+
String :name, :type=>:text
|
23
|
+
Integer :value, :index => true
|
24
24
|
end
|
25
25
|
MSSQL_DB.create_table! :test2 do
|
26
|
-
|
27
|
-
|
26
|
+
String :name, :type=>:text
|
27
|
+
Integer :value
|
28
28
|
end
|
29
29
|
MSSQL_DB.create_table! :test3 do
|
30
|
-
|
31
|
-
|
30
|
+
Integer :value
|
31
|
+
Time :time
|
32
32
|
end
|
33
33
|
MSSQL_DB.create_table! :test4 do
|
34
|
-
|
35
|
-
|
34
|
+
String :name, :size => 20
|
35
|
+
column :value, 'varbinary(max)'
|
36
36
|
end
|
37
37
|
|
38
38
|
describe "A MSSQL database" do
|
@@ -115,7 +115,7 @@ describe "MSSQL Dataset#output" do
|
|
115
115
|
specify "should format OUTPUT clauses without INTO for DELETE statements" do
|
116
116
|
@ds.output(nil, [:deleted__name, :deleted__value]).delete_sql.should =~
|
117
117
|
/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\]/
|
118
|
-
@ds.output(nil, [:deleted
|
118
|
+
@ds.output(nil, [Sequel::SQL::ColumnAll.new(:deleted)]).delete_sql.should =~
|
119
119
|
/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].*/
|
120
120
|
end
|
121
121
|
|
@@ -129,7 +129,7 @@ describe "MSSQL Dataset#output" do
|
|
129
129
|
specify "should format OUTPUT clauses without INTO for INSERT statements" do
|
130
130
|
@ds.output(nil, [:inserted__name, :inserted__value]).insert_sql(:name => "name", :value => 1).should =~
|
131
131
|
/INSERT INTO \[ITEMS\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) OUTPUT \[INSERTED\].\[(NAME|VALUE)\], \[INSERTED\].\[(NAME|VALUE)\] VALUES \((N'name'|1), (N'name'|1)\)/
|
132
|
-
@ds.output(nil, [:inserted
|
132
|
+
@ds.output(nil, [Sequel::SQL::ColumnAll.new(:inserted)]).insert_sql(:name => "name", :value => 1).should =~
|
133
133
|
/INSERT INTO \[ITEMS\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) OUTPUT \[INSERTED\].* VALUES \((N'name'|1), (N'name'|1)\)/
|
134
134
|
end
|
135
135
|
|
@@ -143,7 +143,7 @@ describe "MSSQL Dataset#output" do
|
|
143
143
|
specify "should format OUTPUT clauses without INTO for UPDATE statements" do
|
144
144
|
@ds.output(nil, [:inserted__name, :deleted__value]).update_sql(:value => 2).should =~
|
145
145
|
/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\]/
|
146
|
-
@ds.output(nil, [:inserted
|
146
|
+
@ds.output(nil, [Sequel::SQL::ColumnAll.new(:inserted)]).update_sql(:value => 2).should =~
|
147
147
|
/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[INSERTED\].*/
|
148
148
|
end
|
149
149
|
|
@@ -329,7 +329,7 @@ describe "Common Table Expressions" do
|
|
329
329
|
|
330
330
|
specify "using #with_recursive should be able to update" do
|
331
331
|
ds = @ds.with_recursive(:t, @ds.filter(:parent_id=>1).or(:id => 1), @ds.join(:t, :i=>:parent_id).select(:i1__id, :i1__parent_id), :args=>[:i, :pi])
|
332
|
-
ds.
|
332
|
+
ds.exclude(:id => @db[:t].select(:i)).update(:parent_id => 1)
|
333
333
|
@ds[:id => 1].should == {:id => 1, :parent_id => nil}
|
334
334
|
@ds[:id => 2].should == {:id => 2, :parent_id => 1}
|
335
335
|
@ds[:id => 5].should == {:id => 5, :parent_id => 3}
|
@@ -383,6 +383,7 @@ describe "MSSSQL::Dataset#insert" do
|
|
383
383
|
@ds = @db[:test5]
|
384
384
|
end
|
385
385
|
after do
|
386
|
+
@db[:test4].delete
|
386
387
|
@db.drop_table?(:test5)
|
387
388
|
end
|
388
389
|
|
@@ -400,6 +401,14 @@ describe "MSSSQL::Dataset#insert" do
|
|
400
401
|
h[:value].should == 10
|
401
402
|
@ds.first(:xid=>h[:xid])[:value].should == 10
|
402
403
|
end
|
404
|
+
|
405
|
+
cspecify "should allow large text and binary values", :odbc do
|
406
|
+
blob = Sequel::SQL::Blob.new("0" * (65*1024))
|
407
|
+
@db[:test4].insert(:name => 'max varbinary test', :value => blob)
|
408
|
+
b = @db[:test4].where(:name => 'max varbinary test').get(:value)
|
409
|
+
b.length.should == blob.length
|
410
|
+
b.should == blob
|
411
|
+
end
|
403
412
|
end
|
404
413
|
|
405
414
|
describe "MSSSQL::Dataset#disable_insert_output" do
|
@@ -542,3 +551,19 @@ describe "A MSSQL database adds index with include" do
|
|
542
551
|
@db.indexes(@table_name).should have_key("#{@table_name}_col1_index".to_sym)
|
543
552
|
end
|
544
553
|
end
|
554
|
+
|
555
|
+
describe "MSSQL::Database#drop_column with a schema" do
|
556
|
+
before do
|
557
|
+
MSSQL_DB.run "create schema test" rescue nil
|
558
|
+
end
|
559
|
+
after do
|
560
|
+
MSSQL_DB.drop_table(:test__items)
|
561
|
+
MSSQL_DB.run "drop schema test" rescue nil
|
562
|
+
end
|
563
|
+
|
564
|
+
specify "drops columns with a default value" do
|
565
|
+
MSSQL_DB.create_table!(:test__items){ Integer :id; String :name, :default => 'widget' }
|
566
|
+
MSSQL_DB.drop_column(:test__items, :name)
|
567
|
+
MSSQL_DB[:test__items].columns.should == [:id]
|
568
|
+
end
|
569
|
+
end
|
data/spec/adapters/mysql_spec.rb
CHANGED
@@ -81,7 +81,7 @@ describe "MySQL", '#create_table' do
|
|
81
81
|
@db.schema(:dolls).map{|k, v| v[:auto_increment]}.should == [nil, nil, true]
|
82
82
|
end
|
83
83
|
|
84
|
-
|
84
|
+
specify "should support collate with various other column options" do
|
85
85
|
@db.create_table!(:dolls){ String :name, :size=>128, :collate=>:utf8_bin, :default=>'foo', :null=>false, :unique=>true}
|
86
86
|
@db[:dolls].insert
|
87
87
|
@db[:dolls].select_map(:name).should == ["foo"]
|
@@ -164,72 +164,36 @@ describe "A MySQL dataset" do
|
|
164
164
|
|
165
165
|
specify "should quote columns and tables using back-ticks if quoting identifiers" do
|
166
166
|
@d.quote_identifiers = true
|
167
|
-
@d.select(:name).sql.should ==
|
168
|
-
|
169
|
-
|
170
|
-
@d.select(
|
171
|
-
|
172
|
-
|
173
|
-
@d.select(
|
174
|
-
|
175
|
-
|
176
|
-
@d.select(:
|
177
|
-
'SELECT
|
178
|
-
|
179
|
-
@d.
|
180
|
-
|
181
|
-
|
182
|
-
@d.order(:name.desc).sql.should == \
|
183
|
-
'SELECT * FROM `items` ORDER BY `name` DESC'
|
184
|
-
|
185
|
-
@d.select('items.name AS item_name'.lit).sql.should == \
|
186
|
-
'SELECT items.name AS item_name FROM `items`'
|
187
|
-
|
188
|
-
@d.select('`name`'.lit).sql.should == \
|
189
|
-
'SELECT `name` FROM `items`'
|
190
|
-
|
191
|
-
@d.select('max(items.`name`) AS `max_name`'.lit).sql.should == \
|
192
|
-
'SELECT max(items.`name`) AS `max_name` FROM `items`'
|
193
|
-
|
194
|
-
@d.select(:test.sql_function(:abc, 'hello')).sql.should == \
|
195
|
-
"SELECT test(`abc`, 'hello') FROM `items`"
|
196
|
-
|
197
|
-
@d.select(:test.sql_function(:abc__def, 'hello')).sql.should == \
|
198
|
-
"SELECT test(`abc`.`def`, 'hello') FROM `items`"
|
199
|
-
|
200
|
-
@d.select(:test.sql_function(:abc__def, 'hello').as(:x2)).sql.should == \
|
201
|
-
"SELECT test(`abc`.`def`, 'hello') AS `x2` FROM `items`"
|
202
|
-
|
203
|
-
@d.insert_sql(:value => 333).should == \
|
204
|
-
'INSERT INTO `items` (`value`) VALUES (333)'
|
205
|
-
|
206
|
-
@d.insert_sql(:x => :y).should == \
|
207
|
-
'INSERT INTO `items` (`x`) VALUES (`y`)'
|
167
|
+
@d.select(:name).sql.should == 'SELECT `name` FROM `items`'
|
168
|
+
@d.select(Sequel.lit('COUNT(*)')).sql.should == 'SELECT COUNT(*) FROM `items`'
|
169
|
+
@d.select(Sequel.function(:max, :value)).sql.should == 'SELECT max(`value`) FROM `items`'
|
170
|
+
@d.select(Sequel.function(:NOW)).sql.should == 'SELECT NOW() FROM `items`'
|
171
|
+
@d.select(Sequel.function(:max, :items__value)).sql.should == 'SELECT max(`items`.`value`) FROM `items`'
|
172
|
+
@d.order(Sequel.expr(:name).desc).sql.should == 'SELECT * FROM `items` ORDER BY `name` DESC'
|
173
|
+
@d.select(Sequel.lit('items.name AS item_name')).sql.should == 'SELECT items.name AS item_name FROM `items`'
|
174
|
+
@d.select(Sequel.lit('`name`')).sql.should == 'SELECT `name` FROM `items`'
|
175
|
+
@d.select(Sequel.lit('max(items.`name`) AS `max_name`')).sql.should == 'SELECT max(items.`name`) AS `max_name` FROM `items`'
|
176
|
+
@d.select(Sequel.function(:test, :abc, 'hello')).sql.should == "SELECT test(`abc`, 'hello') FROM `items`"
|
177
|
+
@d.select(Sequel.function(:test, :abc__def, 'hello')).sql.should == "SELECT test(`abc`.`def`, 'hello') FROM `items`"
|
178
|
+
@d.select(Sequel.function(:test, :abc__def, 'hello').as(:x2)).sql.should == "SELECT test(`abc`.`def`, 'hello') AS `x2` FROM `items`"
|
179
|
+
@d.insert_sql(:value => 333).should == 'INSERT INTO `items` (`value`) VALUES (333)'
|
180
|
+
@d.insert_sql(:x => :y).should == 'INSERT INTO `items` (`x`) VALUES (`y`)'
|
208
181
|
end
|
209
182
|
|
210
183
|
specify "should quote fields correctly when reversing the order" do
|
211
184
|
@d.quote_identifiers = true
|
212
|
-
@d.reverse_order(:name).sql.should ==
|
213
|
-
|
214
|
-
|
215
|
-
@d.reverse_order(:name
|
216
|
-
'SELECT * FROM `items` ORDER BY `name` ASC'
|
217
|
-
|
218
|
-
@d.reverse_order(:name, :test.desc).sql.should == \
|
219
|
-
'SELECT * FROM `items` ORDER BY `name` DESC, `test` ASC'
|
220
|
-
|
221
|
-
@d.reverse_order(:name.desc, :test).sql.should == \
|
222
|
-
'SELECT * FROM `items` ORDER BY `name` ASC, `test` DESC'
|
185
|
+
@d.reverse_order(:name).sql.should == 'SELECT * FROM `items` ORDER BY `name` DESC'
|
186
|
+
@d.reverse_order(Sequel.desc(:name)).sql.should == 'SELECT * FROM `items` ORDER BY `name` ASC'
|
187
|
+
@d.reverse_order(:name, Sequel.desc(:test)).sql.should == 'SELECT * FROM `items` ORDER BY `name` DESC, `test` ASC'
|
188
|
+
@d.reverse_order(Sequel.desc(:name), :test).sql.should == 'SELECT * FROM `items` ORDER BY `name` ASC, `test` DESC'
|
223
189
|
end
|
224
190
|
|
225
191
|
specify "should support ORDER clause in UPDATE statements" do
|
226
|
-
@d.order(:name).update_sql(:value => 1).should ==
|
227
|
-
'UPDATE `items` SET `value` = 1 ORDER BY `name`'
|
192
|
+
@d.order(:name).update_sql(:value => 1).should == 'UPDATE `items` SET `value` = 1 ORDER BY `name`'
|
228
193
|
end
|
229
194
|
|
230
195
|
specify "should support LIMIT clause in UPDATE statements" do
|
231
|
-
@d.limit(10).update_sql(:value => 1).should ==
|
232
|
-
'UPDATE `items` SET `value` = 1 LIMIT 10'
|
196
|
+
@d.limit(10).update_sql(:value => 1).should == 'UPDATE `items` SET `value` = 1 LIMIT 10'
|
233
197
|
end
|
234
198
|
|
235
199
|
specify "should support regexps" do
|
@@ -272,9 +236,9 @@ describe "MySQL datasets" do
|
|
272
236
|
@d.quote_identifiers = true
|
273
237
|
market = 'ICE'
|
274
238
|
ack_stamp = Time.now - 15 * 60 # 15 minutes ago
|
275
|
-
@d.select(:market, :minute.
|
276
|
-
where{
|
277
|
-
group_by(:minute.
|
239
|
+
@d.select(:market, Sequel.function(:minute, Sequel.function(:from_unixtime, :ack)).as(:minute)).
|
240
|
+
where{(ack > ack_stamp) & {:market => market}}.
|
241
|
+
group_by(Sequel.function(:minute, Sequel.function(:from_unixtime, :ack))).sql.should == \
|
278
242
|
"SELECT `market`, minute(from_unixtime(`ack`)) AS `minute` FROM `orders` WHERE ((`ack` > #{@d.literal(ack_stamp)}) AND (`market` = 'ICE')) GROUP BY minute(from_unixtime(`ack`))"
|
279
243
|
end
|
280
244
|
end
|
@@ -296,7 +260,7 @@ describe "Dataset#distinct" do
|
|
296
260
|
@ds.insert(20, 10)
|
297
261
|
@ds.insert(30, 10)
|
298
262
|
@ds.order(:b, :a).distinct.map(:a).should == [20, 30]
|
299
|
-
@ds.order(:b, :a
|
263
|
+
@ds.order(:b, Sequel.desc(:a)).distinct.map(:a).should == [30, 20]
|
300
264
|
# MySQL doesn't respect orders when using the nonstandard GROUP BY
|
301
265
|
[[20], [30]].should include(@ds.order(:b, :a).distinct(:b).map(:a))
|
302
266
|
end
|
@@ -1036,25 +1000,25 @@ describe "MySQL::Dataset#complex_expression_sql" do
|
|
1036
1000
|
end
|
1037
1001
|
|
1038
1002
|
specify "should handle pattern matches correctly" do
|
1039
|
-
@d.literal(:x.like('a')).should == "(`x` LIKE BINARY 'a')"
|
1040
|
-
@d.literal(
|
1041
|
-
@d.literal(:x.ilike('a')).should == "(`x` LIKE 'a')"
|
1042
|
-
@d.literal(
|
1043
|
-
@d.literal(:x.like(/a/)).should == "(`x` REGEXP BINARY 'a')"
|
1044
|
-
@d.literal(
|
1045
|
-
@d.literal(:x.like(/a/i)).should == "(`x` REGEXP 'a')"
|
1046
|
-
@d.literal(
|
1003
|
+
@d.literal(Sequel.expr(:x).like('a')).should == "(`x` LIKE BINARY 'a')"
|
1004
|
+
@d.literal(~Sequel.expr(:x).like('a')).should == "(`x` NOT LIKE BINARY 'a')"
|
1005
|
+
@d.literal(Sequel.expr(:x).ilike('a')).should == "(`x` LIKE 'a')"
|
1006
|
+
@d.literal(~Sequel.expr(:x).ilike('a')).should == "(`x` NOT LIKE 'a')"
|
1007
|
+
@d.literal(Sequel.expr(:x).like(/a/)).should == "(`x` REGEXP BINARY 'a')"
|
1008
|
+
@d.literal(~Sequel.expr(:x).like(/a/)).should == "(`x` NOT REGEXP BINARY 'a')"
|
1009
|
+
@d.literal(Sequel.expr(:x).like(/a/i)).should == "(`x` REGEXP 'a')"
|
1010
|
+
@d.literal(~Sequel.expr(:x).like(/a/i)).should == "(`x` NOT REGEXP 'a')"
|
1047
1011
|
end
|
1048
1012
|
|
1049
1013
|
specify "should handle string concatenation with CONCAT if more than one record" do
|
1050
|
-
@d.literal([:x, :y]
|
1051
|
-
@d.literal([:x, :y]
|
1052
|
-
@d.literal([
|
1014
|
+
@d.literal(Sequel.join([:x, :y])).should == "CONCAT(`x`, `y`)"
|
1015
|
+
@d.literal(Sequel.join([:x, :y], ' ')).should == "CONCAT(`x`, ' ', `y`)"
|
1016
|
+
@d.literal(Sequel.join([Sequel.function(:x, :y), 1, Sequel.lit('z')], Sequel.subscript(:y, 1))).should == "CONCAT(x(`y`), `y`[1], '1', `y`[1], z)"
|
1053
1017
|
end
|
1054
1018
|
|
1055
1019
|
specify "should handle string concatenation as simple string if just one record" do
|
1056
|
-
@d.literal([:x]
|
1057
|
-
@d.literal([:x]
|
1020
|
+
@d.literal(Sequel.join([:x])).should == "`x`"
|
1021
|
+
@d.literal(Sequel.join([:x], ' ')).should == "`x`"
|
1058
1022
|
end
|
1059
1023
|
end
|
1060
1024
|
|
@@ -1076,7 +1040,7 @@ describe "MySQL::Dataset#calc_found_rows" do
|
|
1076
1040
|
MYSQL_DB.sqls.clear
|
1077
1041
|
|
1078
1042
|
MYSQL_DB[:items].calc_found_rows.filter(:a => 1).limit(1).all.should == [{:a => 1}]
|
1079
|
-
MYSQL_DB.dataset.select(:FOUND_ROWS.
|
1043
|
+
MYSQL_DB.dataset.select(Sequel.function(:FOUND_ROWS).as(:rows)).all.should == [{:rows => 2 }]
|
1080
1044
|
|
1081
1045
|
MYSQL_DB.sqls.should == [
|
1082
1046
|
'SELECT SQL_CALC_FOUND_ROWS * FROM `items` WHERE (`a` = 1) LIMIT 1',
|