sequel 3.37.0 → 3.38.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 +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',
|