sequel 4.45.0 → 4.46.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|