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
|
@@ -17,13 +17,23 @@ describe "Blockless Ruby Filters" do
|
|
|
17
17
|
@d.l(:x).must_equal 'x'
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
with_symbol_splitting "should support qualified columns and aliased columns using symbols" do
|
|
21
21
|
@d.l(:x__y).must_equal 'x.y'
|
|
22
22
|
@d.l(:x___y).must_equal 'x AS y'
|
|
23
23
|
@d.l(:x__y___z).must_equal 'x.y AS z'
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
deprecated "should support qualified columns and aliased columns using symbols 2" do
|
|
27
|
+
@d.l(:x__y).must_equal 'x.y'
|
|
28
|
+
@d.l(:x___y).must_equal 'x AS y'
|
|
29
|
+
@d.l(:x__y___z).must_equal 'x.y AS z'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
with_symbol_splitting "should support qualified columns using virtual rows" do
|
|
33
|
+
@d.l(Sequel.expr{x__y}).must_equal 'x.y'
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
deprecated "should support qualified columns using virtual rows" do
|
|
27
37
|
@d.l(Sequel.expr{x__y}).must_equal 'x.y'
|
|
28
38
|
end
|
|
29
39
|
|
|
@@ -35,15 +45,15 @@ describe "Blockless Ruby Filters" do
|
|
|
35
45
|
@d.l(:x__y___z).must_equal 'x__y___z'
|
|
36
46
|
@d.l(Sequel.expr{x__y}).must_equal 'x__y'
|
|
37
47
|
ensure
|
|
38
|
-
Sequel.split_symbols =
|
|
48
|
+
Sequel.split_symbols = :deprecated
|
|
39
49
|
end
|
|
40
50
|
end
|
|
41
51
|
|
|
42
52
|
it "should support NOT with SQL functions" do
|
|
43
53
|
@d.l(~Sequel.function(:is_blah)).must_equal 'NOT is_blah()'
|
|
44
54
|
@d.l(~Sequel.function(:is_blah, :x)).must_equal 'NOT is_blah(x)'
|
|
45
|
-
@d.l(~Sequel.function(:is_blah, :
|
|
46
|
-
@d.l(~Sequel.function(:is_blah, :x, :
|
|
55
|
+
@d.l(~Sequel.function(:is_blah, Sequel[:x][:y])).must_equal 'NOT is_blah(x.y)'
|
|
56
|
+
@d.l(~Sequel.function(:is_blah, :x, Sequel[:x][:y])).must_equal 'NOT is_blah(x, x.y)'
|
|
47
57
|
end
|
|
48
58
|
|
|
49
59
|
it "should handle multiple ~" do
|
|
@@ -187,7 +197,7 @@ describe "Blockless Ruby Filters" do
|
|
|
187
197
|
@d.lit(1 + Sequel.expr(:x)).must_equal '(1 + x)'
|
|
188
198
|
@d.lit(2**65 - Sequel.+(:x, 1)).must_equal "(#{2**65} - (x + 1))"
|
|
189
199
|
@d.lit(1.0 / Sequel.function(:x)).must_equal '(1.0 / x())'
|
|
190
|
-
@d.lit(BigDecimal.new('1.0') * Sequel
|
|
200
|
+
@d.lit(BigDecimal.new('1.0') * Sequel[:a][:y]).must_equal '(1.0 * a.y)'
|
|
191
201
|
@d.lit(2 ** Sequel.cast(:x, Integer)).must_equal 'power(2, CAST(x AS integer))'
|
|
192
202
|
@d.lit(1 + Sequel.lit('x')).must_equal '(1 + x)'
|
|
193
203
|
@d.lit(1 + Sequel.lit('?', :x)).must_equal '(1 + x)'
|
|
@@ -320,12 +330,12 @@ describe "Blockless Ruby Filters" do
|
|
|
320
330
|
proc{Sequel::SQL::BooleanExpression.invert(Sequel.expr(:x) + 2)}.must_raise(Sequel::Error)
|
|
321
331
|
end
|
|
322
332
|
|
|
323
|
-
|
|
333
|
+
deprecated "should return self on .lit" do
|
|
324
334
|
y = Sequel.expr(:x) + 1
|
|
325
335
|
y.lit.must_equal y
|
|
326
336
|
end
|
|
327
337
|
|
|
328
|
-
|
|
338
|
+
deprecated "should return have .sql_literal return the literal SQL for the expression" do
|
|
329
339
|
y = Sequel.expr(:x) + 1
|
|
330
340
|
y.sql_literal(@d).must_equal '(x + 1)'
|
|
331
341
|
y.sql_literal(@d).must_equal @d.literal(y)
|
|
@@ -501,13 +511,9 @@ describe "Blockless Ruby Filters" do
|
|
|
501
511
|
end
|
|
502
512
|
|
|
503
513
|
it "should handled emulated function where only name is emulated" do
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
efm = dsc::EMULATED_FUNCTION_MAP.dup
|
|
508
|
-
dsc::EMULATED_FUNCTION_MAP[:trim] = :foo
|
|
509
|
-
dsc.new(@d.db).literal(Sequel.trim(:a)).must_equal 'foo(a)'
|
|
510
|
-
dsc::EMULATED_FUNCTION_MAP.replace(efm)
|
|
514
|
+
ds = Sequel.mock[:a]
|
|
515
|
+
ds.literal(Sequel.trim(:a)).must_equal 'trim(a)'
|
|
516
|
+
ds.with_extend{def native_function_name(f) 'foo' end}.literal(Sequel.trim(:a)).must_equal 'foo(a)'
|
|
511
517
|
end
|
|
512
518
|
|
|
513
519
|
it "should handled emulated function needing full emulation" do
|
|
@@ -535,7 +541,7 @@ describe Sequel::SQL::VirtualRow do
|
|
|
535
541
|
@d.l{column}.must_equal '"column"'
|
|
536
542
|
end
|
|
537
543
|
|
|
538
|
-
|
|
544
|
+
with_symbol_splitting "should treat methods without arguments that have embedded double underscores as qualified identifiers" do
|
|
539
545
|
@d.l{table__column}.must_equal '"table"."column"'
|
|
540
546
|
end
|
|
541
547
|
|
|
@@ -543,24 +549,32 @@ describe Sequel::SQL::VirtualRow do
|
|
|
543
549
|
@d.l{function(arg1, 10, 'arg3')}.must_equal 'function("arg1", 10, \'arg3\')'
|
|
544
550
|
end
|
|
545
551
|
|
|
546
|
-
|
|
552
|
+
deprecated "should treat methods with a block and no arguments as a function call with no arguments" do
|
|
547
553
|
@d.l{version{}}.must_equal 'version()'
|
|
548
554
|
end
|
|
549
555
|
|
|
550
|
-
it "should treat methods
|
|
556
|
+
it "should treat methods followed by function as a function call with no arguments" do
|
|
557
|
+
@d.l{version.function}.must_equal 'version()'
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
deprecated "should treat methods with a block and a leading argument :* as a function call with the SQL wildcard" do
|
|
551
561
|
@d.l{count(:*){}}.must_equal 'count(*)'
|
|
552
562
|
end
|
|
553
563
|
|
|
564
|
+
it "should treat methods followed by function.* as a function call with * argument" do
|
|
565
|
+
@d.l{count.function.*}.must_equal 'count(*)'
|
|
566
|
+
end
|
|
567
|
+
|
|
554
568
|
it "should support * method on functions to raise error if function already has an argument" do
|
|
555
569
|
proc{@d.l{count(1).*}}.must_raise(Sequel::Error)
|
|
556
570
|
end
|
|
557
571
|
|
|
558
572
|
it "should support * method on functions to use * as the argument" do
|
|
559
|
-
@d.l{count
|
|
573
|
+
@d.l{count.function.*}.must_equal 'count(*)'
|
|
560
574
|
@d.literal(Sequel.expr{sum(1) * 2}).must_equal '(sum(1) * 2)'
|
|
561
575
|
end
|
|
562
576
|
|
|
563
|
-
|
|
577
|
+
deprecated "should treat methods with a block and a leading argument :distinct as a function call with DISTINCT and the additional method arguments" do
|
|
564
578
|
@d.l{count(:distinct, column1){}}.must_equal 'count(DISTINCT "column1")'
|
|
565
579
|
@d.l{count(:distinct, column1, column2){}}.must_equal 'count(DISTINCT "column1", "column2")'
|
|
566
580
|
end
|
|
@@ -570,63 +584,109 @@ describe Sequel::SQL::VirtualRow do
|
|
|
570
584
|
@d.l{count(column1, column2).distinct}.must_equal 'count(DISTINCT "column1", "column2")'
|
|
571
585
|
end
|
|
572
586
|
|
|
573
|
-
|
|
587
|
+
deprecated "should raise an error if an unsupported argument is used with a block" do
|
|
574
588
|
proc{@d.where{count(:blah){}}}.must_raise(Sequel::Error)
|
|
575
589
|
end
|
|
576
590
|
|
|
577
|
-
|
|
591
|
+
deprecated "should treat methods with a block and a leading argument :over as a window function call" do
|
|
578
592
|
@d.l{rank(:over){}}.must_equal 'rank() OVER ()'
|
|
579
593
|
end
|
|
580
594
|
|
|
581
|
-
|
|
595
|
+
deprecated "should support :partition options for window function calls" do
|
|
582
596
|
@d.l{rank(:over, :partition=>column1){}}.must_equal 'rank() OVER (PARTITION BY "column1")'
|
|
583
597
|
@d.l{rank(:over, :partition=>[column1, column2]){}}.must_equal 'rank() OVER (PARTITION BY "column1", "column2")'
|
|
584
598
|
end
|
|
585
599
|
|
|
586
|
-
|
|
600
|
+
deprecated "should support :args options for window function calls" do
|
|
587
601
|
@d.l{avg(:over, :args=>column1){}}.must_equal 'avg("column1") OVER ()'
|
|
588
602
|
@d.l{avg(:over, :args=>[column1, column2]){}}.must_equal 'avg("column1", "column2") OVER ()'
|
|
589
603
|
end
|
|
590
604
|
|
|
591
|
-
|
|
605
|
+
deprecated "should support :order option for window function calls" do
|
|
592
606
|
@d.l{rank(:over, :order=>column1){}}.must_equal 'rank() OVER (ORDER BY "column1")'
|
|
593
607
|
@d.l{rank(:over, :order=>[column1, column2]){}}.must_equal 'rank() OVER (ORDER BY "column1", "column2")'
|
|
594
608
|
end
|
|
595
609
|
|
|
596
|
-
|
|
610
|
+
deprecated "should support :window option for window function calls" do
|
|
597
611
|
@d.l{rank(:over, :window=>:win){}}.must_equal 'rank() OVER ("win")'
|
|
598
612
|
end
|
|
599
613
|
|
|
600
|
-
|
|
614
|
+
deprecated "should support :*=>true option for window function calls" do
|
|
601
615
|
@d.l{count(:over, :* =>true){}}.must_equal 'count(*) OVER ()'
|
|
602
616
|
end
|
|
603
617
|
|
|
604
|
-
|
|
618
|
+
deprecated "should support :frame=>:all option for window function calls" do
|
|
605
619
|
@d.l{rank(:over, :frame=>:all){}}.must_equal 'rank() OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)'
|
|
606
620
|
end
|
|
607
621
|
|
|
608
|
-
|
|
622
|
+
deprecated "should support :frame=>:rows option for window function calls" do
|
|
609
623
|
@d.l{rank(:over, :frame=>:rows){}}.must_equal 'rank() OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)'
|
|
610
624
|
end
|
|
611
625
|
|
|
612
|
-
|
|
626
|
+
deprecated "should support :frame=>'some string' option for window function calls" do
|
|
613
627
|
@d.l{rank(:over, :frame=>'RANGE BETWEEN 3 PRECEDING AND CURRENT ROW'){}}.must_equal 'rank() OVER (RANGE BETWEEN 3 PRECEDING AND CURRENT ROW)'
|
|
614
628
|
end
|
|
615
629
|
|
|
616
|
-
|
|
630
|
+
deprecated "should raise an error if an invalid :frame option is used" do
|
|
617
631
|
proc{@d.l{rank(:over, :frame=>:blah){}}}.must_raise(Sequel::Error)
|
|
618
632
|
end
|
|
619
633
|
|
|
620
|
-
|
|
634
|
+
deprecated "should support all these options together" do
|
|
621
635
|
@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)'
|
|
622
636
|
end
|
|
623
637
|
|
|
638
|
+
it "should handle method.function.over as a window function call" do
|
|
639
|
+
@d.l{rank.function.over}.must_equal 'rank() OVER ()'
|
|
640
|
+
end
|
|
641
|
+
|
|
642
|
+
it "should handle method.function.over(:partition) as a window function call" do
|
|
643
|
+
@d.l{rank.function.over(:partition=>column1)}.must_equal 'rank() OVER (PARTITION BY "column1")'
|
|
644
|
+
@d.l{rank.function.over(:partition=>[column1, column2])}.must_equal 'rank() OVER (PARTITION BY "column1", "column2")'
|
|
645
|
+
end
|
|
646
|
+
|
|
647
|
+
it "should handle method(arg).over options as a window function call" do
|
|
648
|
+
@d.l{avg(column1).over}.must_equal 'avg("column1") OVER ()'
|
|
649
|
+
@d.l{avg(column1, column2).over}.must_equal 'avg("column1", "column2") OVER ()'
|
|
650
|
+
end
|
|
651
|
+
|
|
652
|
+
it "should handle method.function.over(:order) as a window function call" do
|
|
653
|
+
@d.l{rank.function.over(:order=>column1)}.must_equal 'rank() OVER (ORDER BY "column1")'
|
|
654
|
+
@d.l{rank.function.over(:order=>[column1, column2])}.must_equal 'rank() OVER (ORDER BY "column1", "column2")'
|
|
655
|
+
end
|
|
656
|
+
|
|
657
|
+
it "should handle method.function.over(:window) as a window function call" do
|
|
658
|
+
@d.l{rank.function.over(:window=>:win)}.must_equal 'rank() OVER ("win")'
|
|
659
|
+
end
|
|
660
|
+
|
|
661
|
+
it "should handle method.function.*.over as a window function call" do
|
|
662
|
+
@d.l{count.function.*.over}.must_equal 'count(*) OVER ()'
|
|
663
|
+
end
|
|
664
|
+
|
|
665
|
+
it "should handle method.function.over(:frame=>:all) as a window function call" do
|
|
666
|
+
@d.l{rank.function.over(:frame=>:all)}.must_equal 'rank() OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)'
|
|
667
|
+
end
|
|
668
|
+
|
|
669
|
+
it "should handle method.function.over(:frame=>:rows) as a window function call" do
|
|
670
|
+
@d.l{rank.function.over(:frame=>:rows)}.must_equal 'rank() OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)'
|
|
671
|
+
end
|
|
672
|
+
|
|
673
|
+
it "should handle method.function.over(:frame=>'some string') as a window function call" do
|
|
674
|
+
@d.l{rank.function.over(:frame=>'RANGE BETWEEN 3 PRECEDING AND CURRENT ROW')}.must_equal 'rank() OVER (RANGE BETWEEN 3 PRECEDING AND CURRENT ROW)'
|
|
675
|
+
end
|
|
676
|
+
|
|
677
|
+
it "should raise an error if an invalid :frame option is used" do
|
|
678
|
+
proc{@d.l{rank.function.over(:frame=>:blah)}}.must_raise(Sequel::Error)
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
it "should support all over options together" do
|
|
682
|
+
@d.l{count.function.*.over(: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)'
|
|
683
|
+
end
|
|
684
|
+
|
|
624
685
|
it "should support order method on functions to specify orders for aggregate functions" do
|
|
625
686
|
@d.l{rank(:c).order(:a, :b)}.must_equal 'rank("c" ORDER BY "a", "b")'
|
|
626
687
|
end
|
|
627
688
|
|
|
628
689
|
it "should support over method on functions to create window functions" do
|
|
629
|
-
@d.l{rank{}.over}.must_equal 'rank() OVER ()'
|
|
630
690
|
@d.l{sum(c).over(:partition=>a, :order=>b, :window=>:win, :frame=>:rows)}.must_equal 'sum("c") OVER ("win" PARTITION BY "a" ORDER BY "b" ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)'
|
|
631
691
|
end
|
|
632
692
|
|
|
@@ -635,36 +695,36 @@ describe Sequel::SQL::VirtualRow do
|
|
|
635
695
|
end
|
|
636
696
|
|
|
637
697
|
it "should raise error if over is called on a function that already has a window " do
|
|
638
|
-
proc{@d.l{rank
|
|
698
|
+
proc{@d.l{rank.function.over.over}}.must_raise(Sequel::Error)
|
|
639
699
|
end
|
|
640
700
|
|
|
641
701
|
it "should raise an error if window functions are not supported" do
|
|
642
|
-
proc{@d.with_extend{def supports_window_functions?; false end}.l{count(:
|
|
643
|
-
proc{Sequel.mock.dataset.filter{count(:
|
|
702
|
+
proc{@d.with_extend{def supports_window_functions?; false end}.l{count.function.*.over(:partition=>a, :order=>b, :window=>:win, :frame=>:rows)}}.must_raise(Sequel::Error)
|
|
703
|
+
proc{Sequel.mock.dataset.filter{count.function.*.over(:partition=>a, :order=>b, :window=>:win, :frame=>:rows)}.sql}.must_raise(Sequel::Error)
|
|
644
704
|
end
|
|
645
705
|
|
|
646
706
|
it "should handle lateral function calls" do
|
|
647
|
-
@d.l{rank
|
|
707
|
+
@d.l{rank.function.lateral}.must_equal 'LATERAL rank()'
|
|
648
708
|
end
|
|
649
709
|
|
|
650
710
|
it "should handle ordered-set and hypothetical-set function calls" do
|
|
651
|
-
@d.l{mode
|
|
652
|
-
@d.l{mode
|
|
711
|
+
@d.l{mode.function.within_group(:a)}.must_equal 'mode() WITHIN GROUP (ORDER BY "a")'
|
|
712
|
+
@d.l{mode.function.within_group(:a, :b)}.must_equal 'mode() WITHIN GROUP (ORDER BY "a", "b")'
|
|
653
713
|
end
|
|
654
714
|
|
|
655
715
|
it "should handle filtered aggregate function calls" do
|
|
656
|
-
@d.l{count
|
|
657
|
-
@d.l{count
|
|
658
|
-
@d.l{count
|
|
659
|
-
@d.l{count
|
|
716
|
+
@d.l{count.function.*.filter(Sequel.&(:a, :b))}.must_equal 'count(*) FILTER (WHERE ("a" AND "b"))'
|
|
717
|
+
@d.l{count.function.*.filter(:a=>1)}.must_equal 'count(*) FILTER (WHERE ("a" = 1))'
|
|
718
|
+
@d.l{count.function.*.filter{b > 1}}.must_equal 'count(*) FILTER (WHERE ("b" > 1))'
|
|
719
|
+
@d.l{count.function.*.filter(:a=>1){b > 1}}.must_equal 'count(*) FILTER (WHERE (("a" = 1) AND ("b" > 1)))'
|
|
660
720
|
end
|
|
661
721
|
|
|
662
722
|
it "should handle fitlered ordered-set and hypothetical-set function calls" do
|
|
663
|
-
@d.l{mode
|
|
723
|
+
@d.l{mode.function.within_group(:a).filter(:a=>1)}.must_equal 'mode() WITHIN GROUP (ORDER BY "a") FILTER (WHERE ("a" = 1))'
|
|
664
724
|
end
|
|
665
725
|
|
|
666
726
|
it "should handle function calls with ordinality" do
|
|
667
|
-
@d.l{foo
|
|
727
|
+
@d.l{foo.function.with_ordinality}.must_equal 'foo() WITH ORDINALITY'
|
|
668
728
|
end
|
|
669
729
|
|
|
670
730
|
it "should support function method on identifiers to create functions" do
|
|
@@ -673,29 +733,44 @@ describe Sequel::SQL::VirtualRow do
|
|
|
673
733
|
@d.l{sum.function(c, 1)}.must_equal 'sum("c", 1)'
|
|
674
734
|
end
|
|
675
735
|
|
|
676
|
-
|
|
736
|
+
with_symbol_splitting "should support function method on foo__bar methods to create functions" do
|
|
677
737
|
@d.l{sch__rank.function}.must_equal 'sch.rank()'
|
|
678
738
|
@d.l{sch__sum.function(c)}.must_equal 'sch.sum("c")'
|
|
679
739
|
@d.l{sch__sum.function(c, 1)}.must_equal 'sch.sum("c", 1)'
|
|
740
|
+
@d.l{Sequel.qualify(sch[:sum], x[:y]).function(c, 1)}.must_equal 'sch.sum.x.y("c", 1)'
|
|
741
|
+
end
|
|
742
|
+
|
|
743
|
+
it "should support function method on qualified identifiers to create functions" do
|
|
744
|
+
@d.l{sch[rank].function}.must_equal 'sch.rank()'
|
|
745
|
+
@d.l{sch[sum].function(c)}.must_equal 'sch.sum("c")'
|
|
746
|
+
@d.l{sch[sum].function(c, 1)}.must_equal 'sch.sum("c", 1)'
|
|
747
|
+
@d.l{Sequel.qualify(sch[:sum], x[:y]).function(c, 1)}.must_equal 'sch.sum.x.y("c", 1)'
|
|
748
|
+
end
|
|
749
|
+
|
|
750
|
+
with_symbol_splitting "should support function method on qualified identifiers to create functions" do
|
|
680
751
|
@d.l{Sequel.qualify(sch__sum, :x__y).function(c, 1)}.must_equal 'sch.sum.x.y("c", 1)'
|
|
681
752
|
end
|
|
682
753
|
|
|
683
|
-
it "should
|
|
754
|
+
it "should not quote function names created from identifiers by default" do
|
|
755
|
+
@d = @d.with_extend{def supports_quoted_function_names?; true end}
|
|
756
|
+
@d.l{rank.function}.must_equal 'rank()'
|
|
757
|
+
end
|
|
758
|
+
|
|
759
|
+
with_symbol_splitting "should handle quoted function names when using double underscores" do
|
|
684
760
|
@d = @d.with_extend{def supports_quoted_function_names?; true end}
|
|
685
|
-
@d.l{rank.function}.must_equal '"rank"()'
|
|
686
761
|
@d.l{sch__rank.function}.must_equal '"sch"."rank"()'
|
|
687
762
|
end
|
|
688
763
|
|
|
689
764
|
it "should quote function names if a quoted function is used and database supports quoted function names" do
|
|
690
765
|
@d = @d.with_extend{def supports_quoted_function_names?; true end}
|
|
691
|
-
@d.l{rank
|
|
692
|
-
@d.l{
|
|
766
|
+
@d.l{rank(1).quoted}.must_equal '"rank"(1)'
|
|
767
|
+
@d.l{rank.function.quoted}.must_equal '"rank"()'
|
|
768
|
+
@d.l{sch__rank(1).quoted}.must_equal '"sch__rank"(1)'
|
|
693
769
|
end
|
|
694
770
|
|
|
695
|
-
it "should not quote function names if an unquoted function is used" do
|
|
771
|
+
it "should not quote function names created from qualified identifiers if an unquoted function is used" do
|
|
696
772
|
@d = @d.with_extend{def supports_quoted_function_names?; true end}
|
|
697
|
-
@d.l{rank.function.unquoted}.must_equal 'rank()'
|
|
698
|
-
@d.l{sch__rank.function.unquoted}.must_equal 'sch.rank()'
|
|
773
|
+
@d.l{sch[rank].function.unquoted}.must_equal 'sch.rank()'
|
|
699
774
|
end
|
|
700
775
|
|
|
701
776
|
it "should deal with classes without requiring :: prefix" do
|
|
@@ -704,7 +779,7 @@ describe Sequel::SQL::VirtualRow do
|
|
|
704
779
|
@d.l{num < Math::PI.to_i}.must_equal "(\"num\" < 3)"
|
|
705
780
|
end
|
|
706
781
|
|
|
707
|
-
|
|
782
|
+
deprecated "should deal with methods added to Object after requiring Sequel" do
|
|
708
783
|
class Object
|
|
709
784
|
def adsoiwemlsdaf; 42; end
|
|
710
785
|
end
|
|
@@ -712,7 +787,7 @@ describe Sequel::SQL::VirtualRow do
|
|
|
712
787
|
@d.l{a > adsoiwemlsdaf}.must_equal '("a" > "adsoiwemlsdaf")'
|
|
713
788
|
end
|
|
714
789
|
|
|
715
|
-
|
|
790
|
+
deprecated "should deal with private methods added to Kernel after requiring Sequel" do
|
|
716
791
|
module Kernel
|
|
717
792
|
private
|
|
718
793
|
def adsoiwemlsdaf2; 42; end
|
|
@@ -737,7 +812,7 @@ describe Sequel::SQL::VirtualRow do
|
|
|
737
812
|
@d.l{|o| o.>=(1, :b)}.must_equal '(1 >= "b")'
|
|
738
813
|
end
|
|
739
814
|
|
|
740
|
-
|
|
815
|
+
deprecated "should have have ` produce literal strings" do
|
|
741
816
|
@d.l{a > `some SQL`}.must_equal '("a" > some SQL)'
|
|
742
817
|
@d.l{|o| o.a > o.`('some SQL')}.must_equal '("a" > some SQL)' #`
|
|
743
818
|
end
|
|
@@ -766,6 +841,9 @@ describe "Sequel core extension replacements" do
|
|
|
766
841
|
Sequel.expr{|o| o.a}.must_be_kind_of(Sequel::SQL::Identifier)
|
|
767
842
|
Sequel.expr{a}.must_be_kind_of(Sequel::SQL::Identifier)
|
|
768
843
|
Sequel.expr(:a).must_be_kind_of(Sequel::SQL::Identifier)
|
|
844
|
+
end
|
|
845
|
+
|
|
846
|
+
with_symbol_splitting "Sequel.expr should return items wrapped in Sequel objects for splittable symbols" do
|
|
769
847
|
Sequel.expr(:a__b).must_be_kind_of(Sequel::SQL::QualifiedIdentifier)
|
|
770
848
|
Sequel.expr(:a___c).must_be_kind_of(Sequel::SQL::AliasedExpression)
|
|
771
849
|
Sequel.expr(:a___c).expression.must_be_kind_of(Sequel::SQL::Identifier)
|
|
@@ -796,12 +874,12 @@ describe "Sequel core extension replacements" do
|
|
|
796
874
|
|
|
797
875
|
it "Sequel.expr should treat blocks/procs as virtual rows and wrap the output" do
|
|
798
876
|
l(Sequel.expr{1} + 1, "(1 + 1)")
|
|
799
|
-
l(Sequel.expr{
|
|
877
|
+
l(Sequel.expr{o[a]} + 1, "(o.a + 1)")
|
|
800
878
|
l(Sequel.expr{[[:a, 1]]} & nil, "((a = 1) AND NULL)")
|
|
801
879
|
l(Sequel.expr{|v| @o} + 1, "(foo + 1)")
|
|
802
880
|
|
|
803
881
|
l(Sequel.expr(proc{1}) + 1, "(1 + 1)")
|
|
804
|
-
l(Sequel.expr(proc{
|
|
882
|
+
l(Sequel.expr(proc{o[a]}) + 1, "(o.a + 1)")
|
|
805
883
|
l(Sequel.expr(proc{[[:a, 1]]}) & nil, "((a = 1) AND NULL)")
|
|
806
884
|
l(Sequel.expr(proc{|v| @o}) + 1, "(foo + 1)")
|
|
807
885
|
end
|
|
@@ -1063,7 +1141,7 @@ describe "Sequel core extension replacements" do
|
|
|
1063
1141
|
|
|
1064
1142
|
it "#* with no arguments should use a ColumnAll for Identifier and QualifiedIdentifier" do
|
|
1065
1143
|
l(Sequel.expr(:a).*, 'a.*')
|
|
1066
|
-
l(Sequel
|
|
1144
|
+
l(Sequel[:a][:b].*, 'a.b.*')
|
|
1067
1145
|
end
|
|
1068
1146
|
|
|
1069
1147
|
it "SQL::Blob should be aliasable and castable by default" do
|
|
@@ -1144,7 +1222,7 @@ describe "Sequel::SQLTime" do
|
|
|
1144
1222
|
@db = Sequel.mock
|
|
1145
1223
|
end
|
|
1146
1224
|
after do
|
|
1147
|
-
Sequel::SQLTime.date = nil
|
|
1225
|
+
Sequel::application_timezone = Sequel::SQLTime.date = nil
|
|
1148
1226
|
end
|
|
1149
1227
|
|
|
1150
1228
|
it ".create should create from hour, minutes, seconds and optional microseconds" do
|
|
@@ -1152,6 +1230,14 @@ describe "Sequel::SQLTime" do
|
|
|
1152
1230
|
@db.literal(Sequel::SQLTime.create(1, 2, 3, 500000)).must_equal "'01:02:03.500000'"
|
|
1153
1231
|
end
|
|
1154
1232
|
|
|
1233
|
+
it ".create should use utc is that is the application_timezone setting" do
|
|
1234
|
+
Sequel::SQLTime.create(1, 2, 3).utc?.must_equal false
|
|
1235
|
+
Sequel::application_timezone = :local
|
|
1236
|
+
Sequel::SQLTime.create(1, 2, 3).utc?.must_equal false
|
|
1237
|
+
Sequel::application_timezone = :utc
|
|
1238
|
+
Sequel::SQLTime.create(1, 2, 3).utc?.must_equal true
|
|
1239
|
+
end
|
|
1240
|
+
|
|
1155
1241
|
it ".create should use today's date by default" do
|
|
1156
1242
|
Sequel::SQLTime.create(1, 2, 3).strftime('%Y-%m-%d').must_equal Date.today.strftime('%Y-%m-%d')
|
|
1157
1243
|
end
|
|
@@ -456,7 +456,7 @@ describe "Sequel Mock Adapter" do
|
|
|
456
456
|
Sequel.mock(:host=>'oracle')[:a].limit(1).with_quote_identifiers(false).sql.upcase.must_equal 'SELECT * FROM (SELECT * FROM A) T1 WHERE (ROWNUM <= 1)'
|
|
457
457
|
Sequel.mock(:host=>'postgres')[:a].full_text_search(:b, 'c').with_quote_identifiers(false).sql.must_equal "SELECT * FROM a WHERE (to_tsvector(CAST('simple' AS regconfig), (COALESCE(b, ''))) @@ to_tsquery(CAST('simple' AS regconfig), 'c'))"
|
|
458
458
|
Sequel.mock(:host=>'sqlanywhere').from(:A).offset(1).with_quote_identifiers(false).sql.must_equal 'SELECT TOP 2147483647 START AT (1 + 1) * FROM A'
|
|
459
|
-
Sequel.mock(:host=>'sqlite')[:
|
|
459
|
+
Sequel.mock(:host=>'sqlite')[Sequel[:a].as(:b)].with_quote_identifiers(false).sql.must_equal "SELECT * FROM a AS 'b'"
|
|
460
460
|
end
|
|
461
461
|
|
|
462
462
|
it "should be able to mock schema calls" do
|
|
@@ -59,6 +59,11 @@ describe Sequel::Dataset, "graphing" do
|
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
it "should requalify currently selected columns in new graph if current dataset joins tables" do
|
|
62
|
+
ds = @ds1.cross_join(:lines).select(Sequel[:points][:id], Sequel[:lines][:id].as(:lid), Sequel[:lines][:x], Sequel[:lines][:y]).graph(@ds3, :x=>:id)
|
|
63
|
+
ds.sql.must_equal 'SELECT points.id, points.lid, points.x, points.y, graphs.id AS graphs_id, graphs.name, graphs.x AS graphs_x, graphs.y AS graphs_y, graphs.lines_x FROM (SELECT points.id, lines.id AS lid, lines.x, lines.y FROM points CROSS JOIN lines) AS points LEFT OUTER JOIN graphs ON (graphs.x = points.id)'
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
with_symbol_splitting "should requalify currently selected columns in new graph if current dataset joins tables with splittable symbols" do
|
|
62
67
|
ds = @ds1.cross_join(:lines).select(:points__id, :lines__id___lid, :lines__x, :lines__y).graph(@ds3, :x=>:id)
|
|
63
68
|
ds.sql.must_equal 'SELECT points.id, points.lid, points.x, points.y, graphs.id AS graphs_id, graphs.name, graphs.x AS graphs_x, graphs.y AS graphs_y, graphs.lines_x FROM (SELECT points.id, lines.id AS lid, lines.x, lines.y FROM points CROSS JOIN lines) AS points LEFT OUTER JOIN graphs ON (graphs.x = points.id)'
|
|
64
69
|
end
|
|
@@ -95,12 +100,17 @@ describe Sequel::Dataset, "graphing" do
|
|
|
95
100
|
ds.sql.must_equal 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
|
|
96
101
|
end
|
|
97
102
|
|
|
98
|
-
|
|
103
|
+
with_symbol_splitting "should accept a schema qualified symbolic table name as the dataset" do
|
|
99
104
|
ds = @ds1.graph(:schema__lines, :x=>:id)
|
|
100
105
|
ds.sql.must_equal 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN schema.lines AS lines ON (lines.x = points.id)'
|
|
101
106
|
end
|
|
102
107
|
|
|
103
|
-
it "
|
|
108
|
+
it "should accept a qualified identifier table name as the dataset" do
|
|
109
|
+
ds = @ds1.graph(Sequel[:schema][:lines], :x=>:id)
|
|
110
|
+
ds.sql.must_equal 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN schema.lines AS lines ON (lines.x = points.id)'
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
with_symbol_splitting "allows giving table alias in symbolic argument" do
|
|
104
114
|
ds = @ds1.graph(:lines___sketch, :x=>:id)
|
|
105
115
|
ds.sql.must_equal 'SELECT points.id, points.x, points.y, sketch.id AS sketch_id, sketch.x AS sketch_x, sketch.y AS sketch_y, sketch.graph_id FROM points LEFT OUTER JOIN lines AS sketch ON (sketch.x = points.id)'
|
|
106
116
|
ds = @ds1.graph(:schema__lines___sketch, :x=>:id)
|
|
@@ -134,18 +144,24 @@ describe Sequel::Dataset, "graphing" do
|
|
|
134
144
|
ds.sql.must_equal 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN schema.lines AS lines ON (lines.x = points.id)'
|
|
135
145
|
end
|
|
136
146
|
|
|
137
|
-
|
|
147
|
+
with_symbol_splitting "should handle a qualified identifier symbol as the source" do
|
|
138
148
|
ds = @ds1.from(:schema__points).graph(:lines, :x=>:id)
|
|
139
149
|
ds.sql.must_equal 'SELECT schema.points.id, schema.points.x, schema.points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM schema.points LEFT OUTER JOIN lines ON (lines.x = schema.points.id)'
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it "should handle a qualified identifier as the source" do
|
|
140
153
|
ds = @ds1.from(Sequel.qualify(:schema, :points)).graph(:lines, :x=>:id)
|
|
141
154
|
ds.sql.must_equal 'SELECT schema.points.id, schema.points.x, schema.points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM schema.points LEFT OUTER JOIN lines ON (lines.x = schema.points.id)'
|
|
142
155
|
end
|
|
143
156
|
|
|
157
|
+
with_symbol_splitting "should accept a SQL::AliasedExpression with splittable symbol as the dataset" do
|
|
158
|
+
ds = @ds1.graph(Sequel.as(:schema__lines, :foo), :x=>:id)
|
|
159
|
+
ds.sql.must_equal 'SELECT points.id, points.x, points.y, foo.id AS foo_id, foo.x AS foo_x, foo.y AS foo_y, foo.graph_id FROM points LEFT OUTER JOIN schema.lines AS foo ON (foo.x = points.id)'
|
|
160
|
+
end
|
|
161
|
+
|
|
144
162
|
it "should accept a SQL::AliasedExpression as the dataset" do
|
|
145
163
|
ds = @ds1.graph(Sequel.as(:lines, :foo), :x=>:id)
|
|
146
164
|
ds.sql.must_equal 'SELECT points.id, points.x, points.y, foo.id AS foo_id, foo.x AS foo_x, foo.y AS foo_y, foo.graph_id FROM points LEFT OUTER JOIN lines AS foo ON (foo.x = points.id)'
|
|
147
|
-
ds = @ds1.graph(Sequel.as(:schema__lines, :foo), :x=>:id)
|
|
148
|
-
ds.sql.must_equal 'SELECT points.id, points.x, points.y, foo.id AS foo_id, foo.x AS foo_x, foo.y AS foo_y, foo.graph_id FROM points LEFT OUTER JOIN schema.lines AS foo ON (foo.x = points.id)'
|
|
149
165
|
ds = @ds1.graph(Sequel.as(Sequel.identifier(:lines), :foo), :x=>:id)
|
|
150
166
|
ds.sql.must_equal 'SELECT points.id, points.x, points.y, foo.id AS foo_id, foo.x AS foo_x, foo.y AS foo_y, foo.graph_id FROM points LEFT OUTER JOIN lines AS foo ON (foo.x = points.id)'
|
|
151
167
|
ds = @ds1.graph(Sequel.as(Sequel.qualify(:schema, :lines), :foo), :x=>:id)
|
|
@@ -196,7 +212,7 @@ describe Sequel::Dataset, "graphing" do
|
|
|
196
212
|
ds.sql.must_equal 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN lines ON ((lines.x = points.id) AND (lines.y = points.id))'
|
|
197
213
|
end
|
|
198
214
|
|
|
199
|
-
|
|
215
|
+
deprecated "should not add columns if graph is called after set_graph_aliases" do
|
|
200
216
|
ds = @ds1.set_graph_aliases([[:x,[:points, :x]], [:y,[:lines, :y]]])
|
|
201
217
|
ds.sql.must_equal 'SELECT points.x, lines.y FROM points'
|
|
202
218
|
ds = ds.graph(:lines, :x=>:id)
|
|
@@ -209,6 +225,11 @@ describe Sequel::Dataset, "graphing" do
|
|
|
209
225
|
end
|
|
210
226
|
|
|
211
227
|
it "should allow graphing of the same dataset multiple times" do
|
|
228
|
+
ds = @ds1.graph(@ds2, :x=>:id).graph(@ds2, {:y=>Sequel[:points][:id]}, :table_alias=>:graph)
|
|
229
|
+
ds.sql.must_equal 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id, graph.id AS graph_id_0, graph.x AS graph_x, graph.y AS graph_y, graph.graph_id AS graph_graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id) LEFT OUTER JOIN lines AS graph ON (graph.y = points.id)'
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
with_symbol_splitting "should allow graphing of the same dataset multiple times when using splittable symbols" do
|
|
212
233
|
ds = @ds1.graph(@ds2, :x=>:id).graph(@ds2, {:y=>:points__id}, :table_alias=>:graph)
|
|
213
234
|
ds.sql.must_equal 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id, graph.id AS graph_id_0, graph.x AS graph_x, graph.y AS graph_y, graph.graph_id AS graph_graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id) LEFT OUTER JOIN lines AS graph ON (graph.y = points.id)'
|
|
214
235
|
end
|
|
@@ -222,7 +243,7 @@ describe Sequel::Dataset, "graphing" do
|
|
|
222
243
|
end
|
|
223
244
|
|
|
224
245
|
describe "#set_graph_aliases" do
|
|
225
|
-
|
|
246
|
+
deprecated "should not modify the current dataset's opts" do
|
|
226
247
|
o1 = @ds1.opts
|
|
227
248
|
o2 = o1.dup
|
|
228
249
|
ds1 = @ds1.set_graph_aliases(:x=>[:graphs,:id])
|
|
@@ -231,6 +252,15 @@ describe Sequel::Dataset, "graphing" do
|
|
|
231
252
|
ds1.opts.wont_equal o1
|
|
232
253
|
end
|
|
233
254
|
|
|
255
|
+
it "should not modify the current dataset's opts" do
|
|
256
|
+
o1 = @ds1.opts
|
|
257
|
+
o2 = o1.dup
|
|
258
|
+
ds1 = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:graphs,:id])
|
|
259
|
+
@ds1.opts.must_equal o1
|
|
260
|
+
@ds1.opts.must_equal o2
|
|
261
|
+
ds1.opts.wont_equal o1
|
|
262
|
+
end
|
|
263
|
+
|
|
234
264
|
it "should specify the graph mapping" do
|
|
235
265
|
ds = @ds1.graph(:lines, :x=>:id)
|
|
236
266
|
ds.sql.must_equal 'SELECT points.id, points.x, points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
|
|
@@ -261,7 +291,7 @@ describe Sequel::Dataset, "graphing" do
|
|
|
261
291
|
].must_include(ds.sql)
|
|
262
292
|
end
|
|
263
293
|
|
|
264
|
-
|
|
294
|
+
deprecated "should only alias columns if necessary" do
|
|
265
295
|
ds = @ds1.set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y])
|
|
266
296
|
['SELECT points.x, lines.y FROM points',
|
|
267
297
|
'SELECT lines.y, points.x FROM points'
|
|
@@ -272,10 +302,22 @@ describe Sequel::Dataset, "graphing" do
|
|
|
272
302
|
'SELECT lines.y, points.x AS x1 FROM points'
|
|
273
303
|
].must_include(ds.sql)
|
|
274
304
|
end
|
|
305
|
+
|
|
306
|
+
it "should only alias columns if necessary" do
|
|
307
|
+
ds = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y])
|
|
308
|
+
['SELECT points.x, lines.y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)',
|
|
309
|
+
'SELECT lines.y, points.x FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
|
|
310
|
+
].must_include(ds.sql)
|
|
311
|
+
|
|
312
|
+
ds = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x1=>[:points, :x], :y=>[:lines, :y])
|
|
313
|
+
['SELECT points.x AS x1, lines.y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)',
|
|
314
|
+
'SELECT lines.y, points.x AS x1 FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
|
|
315
|
+
].must_include(ds.sql)
|
|
316
|
+
end
|
|
275
317
|
end
|
|
276
318
|
|
|
277
319
|
describe "#add_graph_aliases" do
|
|
278
|
-
|
|
320
|
+
deprecated "should not modify the current dataset's opts" do
|
|
279
321
|
ds1 = @ds1.set_graph_aliases(:x=>[:graphs,:id])
|
|
280
322
|
o1 = ds1.opts
|
|
281
323
|
o2 = o1.dup
|
|
@@ -285,6 +327,16 @@ describe Sequel::Dataset, "graphing" do
|
|
|
285
327
|
ds2.opts.wont_equal o1
|
|
286
328
|
end
|
|
287
329
|
|
|
330
|
+
it "should not modify the current dataset's opts" do
|
|
331
|
+
ds1 = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:graphs,:id])
|
|
332
|
+
o1 = ds1.opts
|
|
333
|
+
o2 = o1.dup
|
|
334
|
+
ds2 = ds1.add_graph_aliases(:y=>[:blah,:id])
|
|
335
|
+
ds1.opts.must_equal o1
|
|
336
|
+
ds1.opts.must_equal o2
|
|
337
|
+
ds2.opts.wont_equal o1
|
|
338
|
+
end
|
|
339
|
+
|
|
288
340
|
it "should add columns to the graph mapping" do
|
|
289
341
|
@ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :q]).add_graph_aliases(:y=>[:lines, :r]).sql.must_equal 'SELECT points.q AS x, lines.r AS y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
|
|
290
342
|
end
|