sequel 4.45.0 → 4.46.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.
- checksums.yaml +4 -4
- data/CHANGELOG +108 -0
- data/doc/release_notes/4.46.0.txt +404 -0
- data/doc/security.rdoc +9 -0
- data/doc/sql.rdoc +2 -2
- data/doc/testing.rdoc +1 -1
- data/doc/validations.rdoc +1 -2
- data/lib/sequel/adapters/ado.rb +8 -3
- data/lib/sequel/adapters/ado/access.rb +8 -4
- data/lib/sequel/adapters/ado/mssql.rb +3 -1
- data/lib/sequel/adapters/amalgalite.rb +5 -0
- data/lib/sequel/adapters/cubrid.rb +16 -7
- data/lib/sequel/adapters/do.rb +7 -1
- data/lib/sequel/adapters/do/mysql.rb +8 -4
- data/lib/sequel/adapters/ibmdb.rb +10 -5
- data/lib/sequel/adapters/jdbc.rb +8 -2
- data/lib/sequel/adapters/jdbc/as400.rb +10 -3
- data/lib/sequel/adapters/jdbc/db2.rb +27 -16
- data/lib/sequel/adapters/jdbc/derby.rb +47 -20
- data/lib/sequel/adapters/jdbc/h2.rb +13 -7
- data/lib/sequel/adapters/jdbc/hsqldb.rb +18 -9
- data/lib/sequel/adapters/jdbc/mssql.rb +5 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +3 -2
- data/lib/sequel/adapters/jdbc/oracle.rb +3 -2
- data/lib/sequel/adapters/jdbc/postgresql.rb +4 -3
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +2 -1
- data/lib/sequel/adapters/jdbc/sqlite.rb +10 -3
- data/lib/sequel/adapters/jdbc/sqlserver.rb +23 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +16 -10
- data/lib/sequel/adapters/mock.rb +5 -0
- data/lib/sequel/adapters/mysql.rb +8 -1
- data/lib/sequel/adapters/mysql2.rb +6 -1
- data/lib/sequel/adapters/odbc.rb +20 -8
- data/lib/sequel/adapters/odbc/mssql.rb +6 -3
- data/lib/sequel/adapters/oracle.rb +12 -6
- data/lib/sequel/adapters/postgres.rb +20 -8
- data/lib/sequel/adapters/shared/access.rb +76 -47
- data/lib/sequel/adapters/shared/cubrid.rb +16 -11
- data/lib/sequel/adapters/shared/db2.rb +46 -19
- data/lib/sequel/adapters/shared/firebird.rb +20 -8
- data/lib/sequel/adapters/shared/informix.rb +6 -3
- data/lib/sequel/adapters/shared/mssql.rb +132 -72
- data/lib/sequel/adapters/shared/mysql.rb +112 -65
- data/lib/sequel/adapters/shared/oracle.rb +36 -21
- data/lib/sequel/adapters/shared/postgres.rb +91 -56
- data/lib/sequel/adapters/shared/sqlanywhere.rb +65 -37
- data/lib/sequel/adapters/shared/sqlite.rb +67 -32
- data/lib/sequel/adapters/sqlanywhere.rb +9 -1
- data/lib/sequel/adapters/sqlite.rb +8 -1
- data/lib/sequel/adapters/swift.rb +5 -0
- data/lib/sequel/adapters/swift/mysql.rb +4 -2
- data/lib/sequel/adapters/swift/sqlite.rb +1 -1
- data/lib/sequel/adapters/tinytds.rb +10 -3
- data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +1 -1
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +1 -1
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -0
- data/lib/sequel/adapters/utils/pg_types.rb +14 -6
- data/lib/sequel/adapters/utils/replace.rb +4 -2
- data/lib/sequel/connection_pool/single.rb +2 -2
- data/lib/sequel/core.rb +24 -11
- data/lib/sequel/database/connecting.rb +9 -3
- data/lib/sequel/database/dataset_defaults.rb +7 -1
- data/lib/sequel/database/logging.rb +1 -0
- data/lib/sequel/database/misc.rb +5 -2
- data/lib/sequel/database/query.rb +7 -5
- data/lib/sequel/database/schema_generator.rb +1 -0
- data/lib/sequel/database/schema_methods.rb +50 -27
- data/lib/sequel/database/transactions.rb +19 -9
- data/lib/sequel/dataset/actions.rb +15 -6
- data/lib/sequel/dataset/graph.rb +15 -5
- data/lib/sequel/dataset/misc.rb +12 -4
- data/lib/sequel/dataset/mutation.rb +17 -8
- data/lib/sequel/dataset/prepared_statements.rb +3 -2
- data/lib/sequel/dataset/query.rb +84 -38
- data/lib/sequel/dataset/sql.rb +302 -191
- data/lib/sequel/deprecated.rb +26 -17
- data/lib/sequel/extensions/_deprecated_identifier_mangling.rb +2 -2
- data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
- data/lib/sequel/extensions/from_block.rb +1 -0
- data/lib/sequel/extensions/graph_each.rb +1 -1
- data/lib/sequel/extensions/identifier_mangling.rb +2 -2
- data/lib/sequel/extensions/migration.rb +28 -4
- data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -0
- data/lib/sequel/extensions/schema_dumper.rb +4 -4
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +5 -3
- data/lib/sequel/extensions/set_overrides.rb +2 -0
- data/lib/sequel/extensions/split_array_nil.rb +2 -2
- data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
- data/lib/sequel/model.rb +11 -7
- data/lib/sequel/model/associations.rb +5 -7
- data/lib/sequel/model/base.rb +47 -45
- data/lib/sequel/model/dataset_module.rb +9 -14
- data/lib/sequel/model/plugins.rb +3 -0
- data/lib/sequel/no_core_ext.rb +1 -0
- data/lib/sequel/plugins/blacklist_security.rb +1 -1
- data/lib/sequel/plugins/boolean_subsets.rb +7 -5
- data/lib/sequel/plugins/class_table_inheritance.rb +47 -10
- data/lib/sequel/plugins/dataset_associations.rb +1 -1
- data/lib/sequel/plugins/def_dataset_method.rb +90 -0
- data/lib/sequel/plugins/finder.rb +240 -0
- data/lib/sequel/plugins/inverted_subsets.rb +19 -12
- data/lib/sequel/plugins/many_through_many.rb +1 -1
- data/lib/sequel/plugins/nested_attributes.rb +1 -1
- data/lib/sequel/plugins/schema.rb +1 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +7 -1
- data/lib/sequel/plugins/subset_conditions.rb +11 -3
- data/lib/sequel/plugins/whitelist_security.rb +118 -0
- data/lib/sequel/sql.rb +80 -36
- data/lib/sequel/timezones.rb +2 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +20 -0
- data/spec/adapters/mysql_spec.rb +1 -1
- data/spec/adapters/oracle_spec.rb +12 -8
- data/spec/adapters/postgres_spec.rb +1 -1
- data/spec/adapters/spec_helper.rb +1 -1
- data/spec/adapters/sqlite_spec.rb +36 -34
- data/spec/core/connection_pool_spec.rb +2 -1
- data/spec/core/database_spec.rb +87 -9
- data/spec/core/dataset_spec.rb +501 -129
- data/spec/core/deprecated_spec.rb +1 -1
- data/spec/core/expression_filters_spec.rb +146 -60
- data/spec/core/mock_adapter_spec.rb +1 -1
- data/spec/core/object_graph_spec.rb +61 -9
- data/spec/core/placeholder_literalizer_spec.rb +20 -2
- data/spec/core/schema_generator_spec.rb +6 -6
- data/spec/core/schema_spec.rb +54 -5
- data/spec/core_extensions_spec.rb +122 -18
- data/spec/deprecation_helper.rb +27 -2
- data/spec/extensions/_deprecated_identifier_mangling_spec.rb +6 -6
- data/spec/extensions/association_proxies_spec.rb +2 -2
- data/spec/extensions/auto_literal_strings_spec.rb +212 -0
- data/spec/extensions/blacklist_security_spec.rb +1 -0
- data/spec/extensions/class_table_inheritance_spec.rb +1037 -39
- data/spec/extensions/column_select_spec.rb +20 -8
- data/spec/extensions/columns_introspection_spec.rb +3 -3
- data/spec/extensions/core_refinements_spec.rb +29 -12
- data/spec/extensions/dataset_associations_spec.rb +12 -12
- data/spec/extensions/def_dataset_method_spec.rb +100 -0
- data/spec/extensions/error_sql_spec.rb +1 -1
- data/spec/extensions/finder_spec.rb +260 -0
- data/spec/extensions/graph_each_spec.rb +2 -2
- data/spec/extensions/identifier_mangling_spec.rb +14 -8
- data/spec/extensions/inverted_subsets_spec.rb +4 -4
- data/spec/extensions/lazy_attributes_spec.rb +7 -0
- data/spec/extensions/many_through_many_spec.rb +38 -14
- data/spec/extensions/nested_attributes_spec.rb +18 -6
- data/spec/extensions/no_auto_literal_strings_spec.rb +1 -1
- data/spec/extensions/pg_enum_spec.rb +16 -1
- data/spec/extensions/pg_interval_spec.rb +11 -2
- data/spec/extensions/pg_loose_count_spec.rb +5 -0
- data/spec/extensions/pg_row_spec.rb +25 -0
- data/spec/extensions/prepared_statements_spec.rb +10 -1
- data/spec/extensions/query_spec.rb +2 -2
- data/spec/extensions/schema_dumper_spec.rb +2 -2
- data/spec/extensions/schema_spec.rb +2 -2
- data/spec/extensions/set_overrides_spec.rb +7 -3
- data/spec/extensions/sql_expr_spec.rb +0 -1
- data/spec/extensions/subset_conditions_spec.rb +6 -6
- data/spec/extensions/table_select_spec.rb +24 -12
- data/spec/extensions/to_dot_spec.rb +4 -4
- data/spec/extensions/whitelist_security_spec.rb +131 -0
- data/spec/integration/dataset_test.rb +9 -5
- data/spec/integration/model_test.rb +2 -0
- data/spec/integration/plugin_test.rb +2 -2
- data/spec/integration/spec_helper.rb +1 -1
- data/spec/model/associations_spec.rb +39 -11
- data/spec/model/base_spec.rb +44 -24
- data/spec/model/class_dataset_methods_spec.rb +18 -16
- data/spec/model/dataset_methods_spec.rb +4 -4
- data/spec/model/eager_loading_spec.rb +84 -24
- data/spec/model/model_spec.rb +97 -63
- data/spec/model/record_spec.rb +21 -13
- metadata +13 -2
|
@@ -53,8 +53,19 @@ describe "Dataset::PlaceholderLiteralizer" do
|
|
|
53
53
|
loader = @c.loader(@ds){|pl, ds| ds.where(pl.arg)}
|
|
54
54
|
loader.first(:id=>1).must_equal @h
|
|
55
55
|
loader.first(Sequel.expr{a(b)}).must_equal @h
|
|
56
|
+
@db.sqls.must_equal ["SELECT * FROM items WHERE (id = 1)", "SELECT * FROM items WHERE a(b)"]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
deprecated "should handle calls with a literal strings used as filter arguments" do
|
|
60
|
+
loader = @c.loader(@ds){|pl, ds| ds.where(pl.arg)}
|
|
56
61
|
loader.first("a = 1").must_equal @h
|
|
57
|
-
@db.sqls.must_equal ["SELECT * FROM items WHERE (
|
|
62
|
+
@db.sqls.must_equal ["SELECT * FROM items WHERE (a = 1)"]
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "should handle calls with a literal strings used as filter arguments" do
|
|
66
|
+
loader = @c.loader(@ds){|pl, ds| ds.where(pl.arg)}
|
|
67
|
+
loader.first(Sequel.lit("a = 1")).must_equal @h
|
|
68
|
+
@db.sqls.must_equal ["SELECT * FROM items WHERE (a = 1)"]
|
|
58
69
|
end
|
|
59
70
|
|
|
60
71
|
it "should handle calls with a placeholders used as right hand side of condition specifiers" do
|
|
@@ -72,13 +83,20 @@ describe "Dataset::PlaceholderLiteralizer" do
|
|
|
72
83
|
@db.sqls.must_equal ["SELECT * FROM items WHERE ((a = 1) AND (b = 1))", "SELECT * FROM items WHERE ((a = 2) AND (b = 2))"]
|
|
73
84
|
end
|
|
74
85
|
|
|
75
|
-
|
|
86
|
+
deprecated "should handle calls with a placeholder used multiple times in different capacities" do
|
|
76
87
|
loader = @c.loader(@ds){|pl, ds| a = pl.arg; ds.where(a).where(:b=>a)}
|
|
77
88
|
loader.first("a = 1").must_equal @h
|
|
78
89
|
loader.first(["a = ?", 2]).must_equal @h
|
|
79
90
|
@db.sqls.must_equal ["SELECT * FROM items WHERE ((a = 1) AND (b = 'a = 1'))", "SELECT * FROM items WHERE ((a = 2) AND (b IN ('a = ?', 2)))"]
|
|
80
91
|
end
|
|
81
92
|
|
|
93
|
+
it "should handle calls with a placeholder used multiple times in different capacities" do
|
|
94
|
+
loader = @c.loader(@ds){|pl, ds| a = pl.arg; ds.select(a).where(:b=>a)}
|
|
95
|
+
loader.first("a").must_equal @h
|
|
96
|
+
loader.first(["a = ?", 2]).must_equal @h
|
|
97
|
+
@db.sqls.must_equal ["SELECT 'a' FROM items WHERE (b = 'a')", "SELECT ('a = ?', 2) FROM items WHERE (b IN ('a = ?', 2))"]
|
|
98
|
+
end
|
|
99
|
+
|
|
82
100
|
it "should handle calls with manually specified argument positions" do
|
|
83
101
|
loader = @c.loader(@ds){|pl, ds| ds.where(:a=>pl.arg(1)).where(:b=>pl.arg(0))}
|
|
84
102
|
loader.first(1, 2).must_equal @h
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
|
|
2
2
|
|
|
3
|
-
describe Sequel::Schema::
|
|
3
|
+
describe Sequel::Schema::CreateTableGenerator do
|
|
4
4
|
before do
|
|
5
|
-
@generator = Sequel::Schema::
|
|
5
|
+
@generator = Sequel::Schema::CreateTableGenerator.new(Sequel.mock) do
|
|
6
6
|
string :title
|
|
7
7
|
column :body, :text
|
|
8
8
|
foreign_key :parent_id
|
|
@@ -31,7 +31,7 @@ describe Sequel::Schema::Generator do
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
it "should respect existing column order if primary_key :keep_order is used" do
|
|
34
|
-
generator = Sequel::Schema::
|
|
34
|
+
generator = Sequel::Schema::CreateTableGenerator.new(Sequel.mock) do
|
|
35
35
|
string :title
|
|
36
36
|
primary_key :id, :keep_order=>true
|
|
37
37
|
end
|
|
@@ -44,7 +44,7 @@ describe Sequel::Schema::Generator do
|
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
it "should handle SQL::Identifier and SQL::QualifiedIdentifier as foreign_key arguments" do
|
|
47
|
-
generator = Sequel::Schema::
|
|
47
|
+
generator = Sequel::Schema::CreateTableGenerator.new(Sequel.mock) do
|
|
48
48
|
foreign_key :a_id, Sequel.identifier(:as)
|
|
49
49
|
foreign_key :b_id, Sequel.qualify(:c, :b)
|
|
50
50
|
end
|
|
@@ -182,9 +182,9 @@ describe Sequel::Schema::AlterTableGenerator do
|
|
|
182
182
|
end
|
|
183
183
|
end
|
|
184
184
|
|
|
185
|
-
describe "Sequel::Schema::
|
|
185
|
+
describe "Sequel::Schema::CreateTableGenerator generic type methods" do
|
|
186
186
|
it "should store the type class in :type for each column" do
|
|
187
|
-
Sequel::Schema::
|
|
187
|
+
Sequel::Schema::CreateTableGenerator.new(Sequel.mock) do
|
|
188
188
|
String :a
|
|
189
189
|
Integer :b
|
|
190
190
|
Fixnum :c
|
data/spec/core/schema_spec.rb
CHANGED
|
@@ -10,13 +10,17 @@ describe "DB#create_table" do
|
|
|
10
10
|
@db.sqls.must_equal ['CREATE TABLE cats ()']
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
with_symbol_splitting "should accept the table name with splittable symbols" do
|
|
14
14
|
@db.create_table(:cats__cats) {}
|
|
15
|
+
@db.sqls.must_equal ['CREATE TABLE cats.cats ()']
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should accept the table name in multiple formats" do
|
|
15
19
|
@db.create_table(Sequel[:cats][:cats]) {}
|
|
16
20
|
@db.create_table("cats__cats1") {}
|
|
17
21
|
@db.create_table(Sequel.identifier(:cats__cats2)) {}
|
|
18
22
|
@db.create_table(Sequel.qualify(:cats3, :cats)) {}
|
|
19
|
-
@db.sqls.must_equal ['CREATE TABLE cats.cats ()', 'CREATE TABLE
|
|
23
|
+
@db.sqls.must_equal ['CREATE TABLE cats.cats ()', 'CREATE TABLE cats__cats1 ()', 'CREATE TABLE cats__cats2 ()', 'CREATE TABLE cats3.cats ()']
|
|
20
24
|
end
|
|
21
25
|
|
|
22
26
|
it "should raise an error if the table name argument is not valid" do
|
|
@@ -1495,9 +1499,12 @@ describe "Database#create_view" do
|
|
|
1495
1499
|
@db.sqls.must_equal ['CREATE VIEW test AS SELECT a, b FROM items ORDER BY c WITH LOCAL CHECK OPTION']
|
|
1496
1500
|
end
|
|
1497
1501
|
|
|
1498
|
-
|
|
1502
|
+
with_symbol_splitting "should handle create_or_replace_view with splittable symbols" do
|
|
1499
1503
|
@db.create_or_replace_view :sch__test, "SELECT * FROM xyz"
|
|
1500
1504
|
@db.sqls.must_equal ['DROP VIEW sch.test', 'CREATE VIEW sch.test AS SELECT * FROM xyz']
|
|
1505
|
+
end
|
|
1506
|
+
|
|
1507
|
+
it "should handle create_or_replace_view" do
|
|
1501
1508
|
@db.create_or_replace_view :test, @db[:items].select(:a, :b).order(:c)
|
|
1502
1509
|
@db.sqls.must_equal ['DROP VIEW test', 'CREATE VIEW test AS SELECT a, b FROM items ORDER BY c']
|
|
1503
1510
|
@db.create_or_replace_view Sequel.identifier(:test), @db[:items].select(:a, :b).order(:c)
|
|
@@ -1516,12 +1523,16 @@ describe "Database#drop_view" do
|
|
|
1516
1523
|
@db = Sequel.mock
|
|
1517
1524
|
end
|
|
1518
1525
|
|
|
1526
|
+
with_symbol_splitting "should construct proper SQL for splittable symbols" do
|
|
1527
|
+
@db.drop_view :sch__test
|
|
1528
|
+
@db.sqls.must_equal ['DROP VIEW sch.test']
|
|
1529
|
+
end
|
|
1530
|
+
|
|
1519
1531
|
it "should construct proper SQL" do
|
|
1520
1532
|
@db.drop_view :test
|
|
1521
1533
|
@db.drop_view Sequel.identifier(:test)
|
|
1522
|
-
@db.drop_view :sch__test
|
|
1523
1534
|
@db.drop_view Sequel.qualify(:sch, :test)
|
|
1524
|
-
@db.sqls.must_equal ['DROP VIEW test', 'DROP VIEW test', 'DROP VIEW sch.test'
|
|
1535
|
+
@db.sqls.must_equal ['DROP VIEW test', 'DROP VIEW test', 'DROP VIEW sch.test']
|
|
1525
1536
|
end
|
|
1526
1537
|
|
|
1527
1538
|
it "should drop multiple views at once" do
|
|
@@ -1589,6 +1600,19 @@ describe "Schema Parser" do
|
|
|
1589
1600
|
end
|
|
1590
1601
|
@db.schema(:x)
|
|
1591
1602
|
c.must_equal ["x", {}]
|
|
1603
|
+
@db.schema(Sequel[:s][:x])
|
|
1604
|
+
c.must_equal ["x", {:schema=>"s"}]
|
|
1605
|
+
ds = @db[Sequel[:s][:y]]
|
|
1606
|
+
@db.schema(ds)
|
|
1607
|
+
c.must_equal ["y", {:schema=>"s", :dataset=>ds}]
|
|
1608
|
+
end
|
|
1609
|
+
|
|
1610
|
+
with_symbol_splitting "should provide options if given a table name with splittable symbols" do
|
|
1611
|
+
c = nil
|
|
1612
|
+
meta_def(@db, :schema_parse_table) do |t, opts|
|
|
1613
|
+
c = [t, opts]
|
|
1614
|
+
[[:a, {:db_type=>t.to_s}]]
|
|
1615
|
+
end
|
|
1592
1616
|
@db.schema(:s__x)
|
|
1593
1617
|
c.must_equal ["x", {:schema=>"s"}]
|
|
1594
1618
|
ds = @db[:s__y]
|
|
@@ -1646,6 +1670,31 @@ describe "Schema Parser" do
|
|
|
1646
1670
|
@db.schema(:x).object_id.must_equal s1.object_id
|
|
1647
1671
|
@db.schema(Sequel.identifier(:x)).object_id.must_equal s1.object_id
|
|
1648
1672
|
|
|
1673
|
+
s2 = @db.schema(Sequel[:x][:y])
|
|
1674
|
+
s2.must_equal [['y', {:schema=>'x', :ruby_default=>nil}]]
|
|
1675
|
+
@db.schema(Sequel[:x][:y]).object_id.must_equal s2.object_id
|
|
1676
|
+
@db.schema(Sequel.qualify(:x, :y)).object_id.must_equal s2.object_id
|
|
1677
|
+
|
|
1678
|
+
s2 = @db.schema(Sequel.qualify(:v, Sequel[:x][:y]))
|
|
1679
|
+
s2.must_equal [['y', {:schema=>'x', :ruby_default=>nil, :information_schema_schema=>Sequel.identifier('v')}]]
|
|
1680
|
+
@db.schema(Sequel.qualify(:v, Sequel[:x][:y])).object_id.must_equal s2.object_id
|
|
1681
|
+
@db.schema(Sequel.qualify(Sequel[:v][:x], :y)).object_id.must_equal s2.object_id
|
|
1682
|
+
|
|
1683
|
+
s2 = @db.schema(Sequel.qualify(Sequel[:u][:v], Sequel[:x][:y]))
|
|
1684
|
+
s2.must_equal [['y', {:schema=>'x', :ruby_default=>nil, :information_schema_schema=>Sequel.qualify('u', 'v')}]]
|
|
1685
|
+
@db.schema(Sequel.qualify(Sequel[:u][:v], Sequel[:x][:y])).object_id.must_equal s2.object_id
|
|
1686
|
+
@db.schema(Sequel.qualify(Sequel.qualify(:u, :v), Sequel.qualify(:x, :y))).object_id.must_equal s2.object_id
|
|
1687
|
+
end
|
|
1688
|
+
|
|
1689
|
+
with_symbol_splitting "should convert splittable symbol arguments" do
|
|
1690
|
+
meta_def(@db, :schema_parse_table) do |t, opts|
|
|
1691
|
+
[[t, opts]]
|
|
1692
|
+
end
|
|
1693
|
+
s1 = @db.schema(:x)
|
|
1694
|
+
s1.must_equal [['x', {:ruby_default=>nil}]]
|
|
1695
|
+
@db.schema(:x).object_id.must_equal s1.object_id
|
|
1696
|
+
@db.schema(Sequel.identifier(:x)).object_id.must_equal s1.object_id
|
|
1697
|
+
|
|
1649
1698
|
s2 = @db.schema(:x__y)
|
|
1650
1699
|
s2.must_equal [['y', {:schema=>'x', :ruby_default=>nil}]]
|
|
1651
1700
|
@db.schema(:x__y).object_id.must_equal s2.object_id
|
|
@@ -6,9 +6,8 @@ if ENV['COVERAGE']
|
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
unless Object.const_defined?('Sequel') && Sequel.const_defined?('Model')
|
|
9
|
-
$:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), "
|
|
9
|
+
$:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), "../lib/"))
|
|
10
10
|
require 'sequel'
|
|
11
|
-
Sequel::Deprecation.backtrace_filter = true
|
|
12
11
|
end
|
|
13
12
|
|
|
14
13
|
# SEQUEL5: Remove
|
|
@@ -26,8 +25,13 @@ if RUBY_VERSION < '1.9.0'
|
|
|
26
25
|
Sequel.extension :ruby18_symbol_extensions
|
|
27
26
|
end
|
|
28
27
|
Sequel.extension :symbol_aref
|
|
28
|
+
Sequel.extension :virtual_row_method_block
|
|
29
29
|
|
|
30
|
+
gem 'minitest'
|
|
30
31
|
require 'minitest/autorun'
|
|
32
|
+
require 'minitest/hooks/default'
|
|
33
|
+
|
|
34
|
+
require File.expand_path("#{File.dirname(__FILE__)}/deprecation_helper.rb")
|
|
31
35
|
|
|
32
36
|
describe "Sequel core extensions" do
|
|
33
37
|
it "should have Sequel.core_extensions? be true if enabled" do
|
|
@@ -90,6 +94,9 @@ describe "Core extensions" do
|
|
|
90
94
|
end
|
|
91
95
|
it "should support NOT via Symbol#~" do
|
|
92
96
|
@d.l(~:x).must_equal 'NOT x'
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
with_symbol_splitting "should support NOT via Symbol#~ for splittable symbols" do
|
|
93
100
|
@d.l(~:x__y).must_equal 'NOT x.y'
|
|
94
101
|
end
|
|
95
102
|
|
|
@@ -231,7 +238,7 @@ describe "Core extensions" do
|
|
|
231
238
|
@d.lit([:x.sql_function(1), 'y.z'.lit].sql_string_join(', ')).must_equal "(x(1) || ', ' || y.z)"
|
|
232
239
|
@d.lit([:x, 1, :y].sql_string_join).must_equal "(x || '1' || y)"
|
|
233
240
|
@d.lit([:x, 1, :y].sql_string_join(', ')).must_equal "(x || ', ' || '1' || ', ' || y)"
|
|
234
|
-
@d.lit([:x, 1, :y].sql_string_join(:
|
|
241
|
+
@d.lit([:x, 1, :y].sql_string_join(Sequel[:y][:z])).must_equal "(x || y.z || '1' || y.z || y)"
|
|
235
242
|
@d.lit([:x, 1, :y].sql_string_join(1)).must_equal "(x || '1' || '1' || '1' || y)"
|
|
236
243
|
@d.lit([:x, :y].sql_string_join('y.x || x.y'.lit)).must_equal "(x || y.x || x.y || y)"
|
|
237
244
|
@d.lit([[:x, :y].sql_string_join, [:a, :b].sql_string_join].sql_string_join).must_equal "(x || y || a || b)"
|
|
@@ -282,7 +289,7 @@ describe "Array#case and Hash#case" do
|
|
|
282
289
|
@d.literal([[:x, :y]].case(:z)).must_equal '(CASE WHEN x THEN y ELSE z END)'
|
|
283
290
|
@d.literal([[:x, :y], [:a, :b]].case(:z)).must_equal '(CASE WHEN x THEN y WHEN a THEN b ELSE z END)'
|
|
284
291
|
@d.literal([[:x, :y], [:a, :b]].case(:z, :exp)).must_equal '(CASE exp WHEN x THEN y WHEN a THEN b ELSE z END)'
|
|
285
|
-
@d.literal([[:x, :y], [:a, :b]].case(:z, :
|
|
292
|
+
@d.literal([[:x, :y], [:a, :b]].case(:z, Sequel[:exp][:w])).must_equal '(CASE exp.w WHEN x THEN y WHEN a THEN b ELSE z END)'
|
|
286
293
|
end
|
|
287
294
|
|
|
288
295
|
it "should return SQL CASE expression with expression even if nil" do
|
|
@@ -307,9 +314,9 @@ describe "Array#sql_value_list and #sql_array" do
|
|
|
307
314
|
end
|
|
308
315
|
|
|
309
316
|
it "should treat the array as an SQL value list instead of conditions when used as a placeholder value" do
|
|
310
|
-
@d.filter("(a, b) IN ?", [[:x, 1], [:y, 2]]).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x = 1) AND (y = 2)))'
|
|
311
|
-
@d.filter("(a, b) IN ?", [[:x, 1], [:y, 2]].sql_value_list).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
|
|
312
|
-
@d.filter("(a, b) IN ?", [[:x, 1], [:y, 2]].sql_array).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
|
|
317
|
+
@d.filter(Sequel.lit("(a, b) IN ?", [[:x, 1], [:y, 2]])).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x = 1) AND (y = 2)))'
|
|
318
|
+
@d.filter(Sequel.lit("(a, b) IN ?", [[:x, 1], [:y, 2]].sql_value_list)).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
|
|
319
|
+
@d.filter(Sequel.lit("(a, b) IN ?", [[:x, 1], [:y, 2]].sql_array)).sql.must_equal 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
|
|
313
320
|
end
|
|
314
321
|
|
|
315
322
|
it "should be no difference when used as a hash value" do
|
|
@@ -401,7 +408,9 @@ describe "#desc" do
|
|
|
401
408
|
|
|
402
409
|
it "should format a DESC clause for a column ref" do
|
|
403
410
|
@ds.literal(:test.desc).must_equal 'test DESC'
|
|
411
|
+
end
|
|
404
412
|
|
|
413
|
+
with_symbol_splitting "should format a DESC clause for a column ref with a splitting symbol" do
|
|
405
414
|
@ds.literal(:items__price.desc).must_equal 'items.price DESC'
|
|
406
415
|
end
|
|
407
416
|
|
|
@@ -417,7 +426,9 @@ describe "#asc" do
|
|
|
417
426
|
|
|
418
427
|
it "should format a ASC clause for a column ref" do
|
|
419
428
|
@ds.literal(:test.asc).must_equal 'test ASC'
|
|
429
|
+
end
|
|
420
430
|
|
|
431
|
+
with_symbol_splitting "should format a ASC clause for a column ref for a splittable symbol" do
|
|
421
432
|
@ds.literal(:items__price.asc).must_equal 'items.price ASC'
|
|
422
433
|
end
|
|
423
434
|
|
|
@@ -433,7 +444,9 @@ describe "#as" do
|
|
|
433
444
|
|
|
434
445
|
it "should format a AS clause for a column ref" do
|
|
435
446
|
@ds.literal(:test.as(:t)).must_equal 'test AS t'
|
|
436
|
-
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
with_symbol_splitting "should format a AS clause for a column ref for splittable symbols" do
|
|
437
450
|
@ds.literal(:items__price.as(:p)).must_equal 'items.price AS p'
|
|
438
451
|
end
|
|
439
452
|
|
|
@@ -453,15 +466,9 @@ describe "Column references" do
|
|
|
453
466
|
|
|
454
467
|
it "should be quoted properly" do
|
|
455
468
|
@ds.literal(:xyz).must_equal "`xyz`"
|
|
456
|
-
@ds.literal(:xyz__abc).must_equal "`xyz`.`abc`"
|
|
457
|
-
|
|
458
469
|
@ds.literal(:xyz.as(:x)).must_equal "`xyz` AS `x`"
|
|
459
|
-
@ds.literal(:xyz__abc.as(:x)).must_equal "`xyz`.`abc` AS `x`"
|
|
460
|
-
|
|
461
|
-
@ds.literal(:xyz___x).must_equal "`xyz` AS `x`"
|
|
462
|
-
@ds.literal(:xyz__abc___x).must_equal "`xyz`.`abc` AS `x`"
|
|
463
470
|
end
|
|
464
|
-
|
|
471
|
+
|
|
465
472
|
it "should be quoted properly in SQL functions" do
|
|
466
473
|
@ds.literal(:avg.sql_function(:xyz)).must_equal "avg(`xyz`)"
|
|
467
474
|
@ds.literal(:avg.sql_function(:xyz, 1)).must_equal "avg(`xyz`, 1)"
|
|
@@ -475,6 +482,13 @@ describe "Column references" do
|
|
|
475
482
|
|
|
476
483
|
it "should be quoted properly in a cast function" do
|
|
477
484
|
@ds.literal(:x.cast(:integer)).must_equal "CAST(`x` AS integer)"
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
with_symbol_splitting "should be quoted properly when using symbol splitting" do
|
|
488
|
+
@ds.literal(:xyz__abc).must_equal "`xyz`.`abc`"
|
|
489
|
+
@ds.literal(:xyz__abc.as(:x)).must_equal "`xyz`.`abc` AS `x`"
|
|
490
|
+
@ds.literal(:xyz___x).must_equal "`xyz` AS `x`"
|
|
491
|
+
@ds.literal(:xyz__abc___x).must_equal "`xyz`.`abc` AS `x`"
|
|
478
492
|
@ds.literal(:x__y.cast('varchar(20)')).must_equal "CAST(`x`.`y` AS varchar(20))"
|
|
479
493
|
end
|
|
480
494
|
end
|
|
@@ -512,7 +526,7 @@ describe "Symbol#*" do
|
|
|
512
526
|
@ds.literal(:abc.*(5)).must_equal '(abc * 5)'
|
|
513
527
|
end
|
|
514
528
|
|
|
515
|
-
|
|
529
|
+
with_symbol_splitting "should support qualified symbols if no argument" do
|
|
516
530
|
@ds.literal(:xyz__abc.*).must_equal 'xyz.abc.*'
|
|
517
531
|
end
|
|
518
532
|
end
|
|
@@ -534,7 +548,7 @@ describe "Symbol" do
|
|
|
534
548
|
@ds.literal(:xyz.qualify(:abc).qualify(:def)).must_equal '"def"."abc"."xyz"'
|
|
535
549
|
end
|
|
536
550
|
|
|
537
|
-
|
|
551
|
+
with_symbol_splitting "should be able to qualify an identifier" do
|
|
538
552
|
@ds.literal(:xyz.identifier.qualify(:xyz__abc)).must_equal '"xyz"."abc"."xyz"'
|
|
539
553
|
end
|
|
540
554
|
|
|
@@ -575,11 +589,14 @@ describe "Symbol" do
|
|
|
575
589
|
|
|
576
590
|
it "should support sql array accesses via sql_subscript" do
|
|
577
591
|
@ds.literal(:abc.sql_subscript(1)).must_equal "abc[1]"
|
|
578
|
-
@ds.literal(:abc__def.sql_subscript(1)).must_equal "abc.def[1]"
|
|
579
592
|
@ds.literal(:abc.sql_subscript(1)|2).must_equal "abc[1, 2]"
|
|
580
593
|
@ds.literal(:abc.sql_subscript(1)[2]).must_equal "abc[1][2]"
|
|
581
594
|
end
|
|
582
595
|
|
|
596
|
+
with_symbol_splitting "should support sql array accesses via sql_subscript for splittable symbols" do
|
|
597
|
+
@ds.literal(:abc__def.sql_subscript(1)).must_equal "abc.def[1]"
|
|
598
|
+
end
|
|
599
|
+
|
|
583
600
|
it "should support cast_numeric and cast_string" do
|
|
584
601
|
x = :abc.cast_numeric
|
|
585
602
|
x.must_be_kind_of(Sequel::SQL::NumericExpression)
|
|
@@ -726,3 +743,90 @@ describe "symbol_aref extensions" do
|
|
|
726
743
|
end
|
|
727
744
|
end
|
|
728
745
|
end
|
|
746
|
+
|
|
747
|
+
describe Sequel::SQL::VirtualRow do
|
|
748
|
+
before do
|
|
749
|
+
@d = Sequel.mock[:items].with_quote_identifiers(true).with_extend do
|
|
750
|
+
def supports_window_functions?; true end
|
|
751
|
+
def l(*args, &block)
|
|
752
|
+
literal(filter_expr(*args, &block))
|
|
753
|
+
end
|
|
754
|
+
end
|
|
755
|
+
end
|
|
756
|
+
|
|
757
|
+
it "should treat methods without blocks normally" do
|
|
758
|
+
@d.l{column}.must_equal '"column"'
|
|
759
|
+
@d.l{foo(a)}.must_equal 'foo("a")'
|
|
760
|
+
end
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
it "should treat methods with a block and no arguments as a function call with no arguments" do
|
|
764
|
+
@d.l{version{}}.must_equal 'version()'
|
|
765
|
+
end
|
|
766
|
+
|
|
767
|
+
it "should treat methods with a block and a leading argument :* as a function call with the SQL wildcard" do
|
|
768
|
+
@d.l{count(:*){}}.must_equal 'count(*)'
|
|
769
|
+
end
|
|
770
|
+
|
|
771
|
+
it "should treat methods with a block and a leading argument :distinct as a function call with DISTINCT and the additional method arguments" do
|
|
772
|
+
@d.l{count(:distinct, column1){}}.must_equal 'count(DISTINCT "column1")'
|
|
773
|
+
@d.l{count(:distinct, column1, column2){}}.must_equal 'count(DISTINCT "column1", "column2")'
|
|
774
|
+
end
|
|
775
|
+
|
|
776
|
+
it "should raise an error if an unsupported argument is used with a block" do
|
|
777
|
+
proc{@d.where{count(:blah){}}}.must_raise(Sequel::Error)
|
|
778
|
+
end
|
|
779
|
+
|
|
780
|
+
it "should treat methods with a block and a leading argument :over as a window function call" do
|
|
781
|
+
@d.l{rank(:over){}}.must_equal 'rank() OVER ()'
|
|
782
|
+
end
|
|
783
|
+
|
|
784
|
+
it "should support :partition options for window function calls" do
|
|
785
|
+
@d.l{rank(:over, :partition=>column1){}}.must_equal 'rank() OVER (PARTITION BY "column1")'
|
|
786
|
+
@d.l{rank(:over, :partition=>[column1, column2]){}}.must_equal 'rank() OVER (PARTITION BY "column1", "column2")'
|
|
787
|
+
end
|
|
788
|
+
|
|
789
|
+
it "should support :args options for window function calls" do
|
|
790
|
+
@d.l{avg(:over, :args=>column1){}}.must_equal 'avg("column1") OVER ()'
|
|
791
|
+
@d.l{avg(:over, :args=>[column1, column2]){}}.must_equal 'avg("column1", "column2") OVER ()'
|
|
792
|
+
end
|
|
793
|
+
|
|
794
|
+
it "should support :order option for window function calls" do
|
|
795
|
+
@d.l{rank(:over, :order=>column1){}}.must_equal 'rank() OVER (ORDER BY "column1")'
|
|
796
|
+
@d.l{rank(:over, :order=>[column1, column2]){}}.must_equal 'rank() OVER (ORDER BY "column1", "column2")'
|
|
797
|
+
end
|
|
798
|
+
|
|
799
|
+
it "should support :window option for window function calls" do
|
|
800
|
+
@d.l{rank(:over, :window=>:win){}}.must_equal 'rank() OVER ("win")'
|
|
801
|
+
end
|
|
802
|
+
|
|
803
|
+
it "should support :*=>true option for window function calls" do
|
|
804
|
+
@d.l{count(:over, :* =>true){}}.must_equal 'count(*) OVER ()'
|
|
805
|
+
end
|
|
806
|
+
|
|
807
|
+
it "should support :frame=>:all option for window function calls" do
|
|
808
|
+
@d.l{rank(:over, :frame=>:all){}}.must_equal 'rank() OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)'
|
|
809
|
+
end
|
|
810
|
+
|
|
811
|
+
it "should support :frame=>:rows option for window function calls" do
|
|
812
|
+
@d.l{rank(:over, :frame=>:rows){}}.must_equal 'rank() OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)'
|
|
813
|
+
end
|
|
814
|
+
|
|
815
|
+
it "should support :frame=>'some string' option for window function calls" do
|
|
816
|
+
@d.l{rank(:over, :frame=>'RANGE BETWEEN 3 PRECEDING AND CURRENT ROW'){}}.must_equal 'rank() OVER (RANGE BETWEEN 3 PRECEDING AND CURRENT ROW)'
|
|
817
|
+
end
|
|
818
|
+
|
|
819
|
+
it "should raise an error if an invalid :frame option is used" do
|
|
820
|
+
proc{@d.l{rank(:over, :frame=>:blah){}}}.must_raise(Sequel::Error)
|
|
821
|
+
end
|
|
822
|
+
|
|
823
|
+
it "should support all these options together" do
|
|
824
|
+
@d.l{count(:over, :* =>true, :partition=>a, :order=>b, :window=>:win, :frame=>:rows){}}.must_equal 'count(*) OVER ("win" PARTITION BY "a" ORDER BY "b" ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)'
|
|
825
|
+
end
|
|
826
|
+
|
|
827
|
+
it "should raise an error if window functions are not supported" do
|
|
828
|
+
proc{@d.with_extend{def supports_window_functions?; false end}.l{count(:over, :* =>true, :partition=>a, :order=>b, :window=>:win, :frame=>:rows){}}}.must_raise(Sequel::Error)
|
|
829
|
+
proc{Sequel.mock.dataset.filter{count(:over, :* =>true, :partition=>a, :order=>b, :window=>:win, :frame=>:rows){}}.sql}.must_raise(Sequel::Error)
|
|
830
|
+
end
|
|
831
|
+
end
|
|
832
|
+
|
data/spec/deprecation_helper.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Sequel::Deprecation.backtrace_filter = lambda{|line, lineno| lineno < 4 || line =~ /_spec\.rb/}
|
|
2
2
|
|
|
3
3
|
class Minitest::HooksSpec
|
|
4
|
-
def self.deprecated(
|
|
5
|
-
it(
|
|
4
|
+
def self.deprecated(a, &block)
|
|
5
|
+
it("#{a} (deprecated)") do
|
|
6
6
|
deprecated{instance_exec(&block)}
|
|
7
7
|
end
|
|
8
8
|
end
|
|
@@ -14,4 +14,29 @@ class Minitest::HooksSpec
|
|
|
14
14
|
ensure
|
|
15
15
|
Sequel::Deprecation.output = output
|
|
16
16
|
end
|
|
17
|
+
|
|
18
|
+
def self.with_symbol_splitting(a, &block)
|
|
19
|
+
it(a) do
|
|
20
|
+
with_symbol_splitting{instance_exec(&block)}
|
|
21
|
+
end
|
|
22
|
+
it("#{a}, except when symbol_splitting disabled") do
|
|
23
|
+
without_symbol_splitting{instance_exec(&block)}
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def without_symbol_splitting
|
|
28
|
+
Sequel.split_symbols = false
|
|
29
|
+
DB.send(:reset_default_dataset) if defined?(DB)
|
|
30
|
+
proc{yield}.must_raise Minitest::Assertion
|
|
31
|
+
ensure
|
|
32
|
+
Sequel.split_symbols = :deprecated
|
|
33
|
+
DB.send(:reset_default_dataset) if defined?(DB)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def with_symbol_splitting
|
|
37
|
+
Sequel.split_symbols = true
|
|
38
|
+
yield
|
|
39
|
+
ensure
|
|
40
|
+
Sequel.split_symbols = :deprecated
|
|
41
|
+
end
|
|
17
42
|
end
|