sequel 4.45.0 → 4.46.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +108 -0
  3. data/doc/release_notes/4.46.0.txt +404 -0
  4. data/doc/security.rdoc +9 -0
  5. data/doc/sql.rdoc +2 -2
  6. data/doc/testing.rdoc +1 -1
  7. data/doc/validations.rdoc +1 -2
  8. data/lib/sequel/adapters/ado.rb +8 -3
  9. data/lib/sequel/adapters/ado/access.rb +8 -4
  10. data/lib/sequel/adapters/ado/mssql.rb +3 -1
  11. data/lib/sequel/adapters/amalgalite.rb +5 -0
  12. data/lib/sequel/adapters/cubrid.rb +16 -7
  13. data/lib/sequel/adapters/do.rb +7 -1
  14. data/lib/sequel/adapters/do/mysql.rb +8 -4
  15. data/lib/sequel/adapters/ibmdb.rb +10 -5
  16. data/lib/sequel/adapters/jdbc.rb +8 -2
  17. data/lib/sequel/adapters/jdbc/as400.rb +10 -3
  18. data/lib/sequel/adapters/jdbc/db2.rb +27 -16
  19. data/lib/sequel/adapters/jdbc/derby.rb +47 -20
  20. data/lib/sequel/adapters/jdbc/h2.rb +13 -7
  21. data/lib/sequel/adapters/jdbc/hsqldb.rb +18 -9
  22. data/lib/sequel/adapters/jdbc/mssql.rb +5 -2
  23. data/lib/sequel/adapters/jdbc/mysql.rb +3 -2
  24. data/lib/sequel/adapters/jdbc/oracle.rb +3 -2
  25. data/lib/sequel/adapters/jdbc/postgresql.rb +4 -3
  26. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +2 -1
  27. data/lib/sequel/adapters/jdbc/sqlite.rb +10 -3
  28. data/lib/sequel/adapters/jdbc/sqlserver.rb +23 -0
  29. data/lib/sequel/adapters/jdbc/transactions.rb +16 -10
  30. data/lib/sequel/adapters/mock.rb +5 -0
  31. data/lib/sequel/adapters/mysql.rb +8 -1
  32. data/lib/sequel/adapters/mysql2.rb +6 -1
  33. data/lib/sequel/adapters/odbc.rb +20 -8
  34. data/lib/sequel/adapters/odbc/mssql.rb +6 -3
  35. data/lib/sequel/adapters/oracle.rb +12 -6
  36. data/lib/sequel/adapters/postgres.rb +20 -8
  37. data/lib/sequel/adapters/shared/access.rb +76 -47
  38. data/lib/sequel/adapters/shared/cubrid.rb +16 -11
  39. data/lib/sequel/adapters/shared/db2.rb +46 -19
  40. data/lib/sequel/adapters/shared/firebird.rb +20 -8
  41. data/lib/sequel/adapters/shared/informix.rb +6 -3
  42. data/lib/sequel/adapters/shared/mssql.rb +132 -72
  43. data/lib/sequel/adapters/shared/mysql.rb +112 -65
  44. data/lib/sequel/adapters/shared/oracle.rb +36 -21
  45. data/lib/sequel/adapters/shared/postgres.rb +91 -56
  46. data/lib/sequel/adapters/shared/sqlanywhere.rb +65 -37
  47. data/lib/sequel/adapters/shared/sqlite.rb +67 -32
  48. data/lib/sequel/adapters/sqlanywhere.rb +9 -1
  49. data/lib/sequel/adapters/sqlite.rb +8 -1
  50. data/lib/sequel/adapters/swift.rb +5 -0
  51. data/lib/sequel/adapters/swift/mysql.rb +4 -2
  52. data/lib/sequel/adapters/swift/sqlite.rb +1 -1
  53. data/lib/sequel/adapters/tinytds.rb +10 -3
  54. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +1 -1
  55. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +1 -1
  56. data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -0
  57. data/lib/sequel/adapters/utils/pg_types.rb +14 -6
  58. data/lib/sequel/adapters/utils/replace.rb +4 -2
  59. data/lib/sequel/connection_pool/single.rb +2 -2
  60. data/lib/sequel/core.rb +24 -11
  61. data/lib/sequel/database/connecting.rb +9 -3
  62. data/lib/sequel/database/dataset_defaults.rb +7 -1
  63. data/lib/sequel/database/logging.rb +1 -0
  64. data/lib/sequel/database/misc.rb +5 -2
  65. data/lib/sequel/database/query.rb +7 -5
  66. data/lib/sequel/database/schema_generator.rb +1 -0
  67. data/lib/sequel/database/schema_methods.rb +50 -27
  68. data/lib/sequel/database/transactions.rb +19 -9
  69. data/lib/sequel/dataset/actions.rb +15 -6
  70. data/lib/sequel/dataset/graph.rb +15 -5
  71. data/lib/sequel/dataset/misc.rb +12 -4
  72. data/lib/sequel/dataset/mutation.rb +17 -8
  73. data/lib/sequel/dataset/prepared_statements.rb +3 -2
  74. data/lib/sequel/dataset/query.rb +84 -38
  75. data/lib/sequel/dataset/sql.rb +302 -191
  76. data/lib/sequel/deprecated.rb +26 -17
  77. data/lib/sequel/extensions/_deprecated_identifier_mangling.rb +2 -2
  78. data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
  79. data/lib/sequel/extensions/from_block.rb +1 -0
  80. data/lib/sequel/extensions/graph_each.rb +1 -1
  81. data/lib/sequel/extensions/identifier_mangling.rb +2 -2
  82. data/lib/sequel/extensions/migration.rb +28 -4
  83. data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -0
  84. data/lib/sequel/extensions/schema_dumper.rb +4 -4
  85. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +5 -3
  86. data/lib/sequel/extensions/set_overrides.rb +2 -0
  87. data/lib/sequel/extensions/split_array_nil.rb +2 -2
  88. data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
  89. data/lib/sequel/model.rb +11 -7
  90. data/lib/sequel/model/associations.rb +5 -7
  91. data/lib/sequel/model/base.rb +47 -45
  92. data/lib/sequel/model/dataset_module.rb +9 -14
  93. data/lib/sequel/model/plugins.rb +3 -0
  94. data/lib/sequel/no_core_ext.rb +1 -0
  95. data/lib/sequel/plugins/blacklist_security.rb +1 -1
  96. data/lib/sequel/plugins/boolean_subsets.rb +7 -5
  97. data/lib/sequel/plugins/class_table_inheritance.rb +47 -10
  98. data/lib/sequel/plugins/dataset_associations.rb +1 -1
  99. data/lib/sequel/plugins/def_dataset_method.rb +90 -0
  100. data/lib/sequel/plugins/finder.rb +240 -0
  101. data/lib/sequel/plugins/inverted_subsets.rb +19 -12
  102. data/lib/sequel/plugins/many_through_many.rb +1 -1
  103. data/lib/sequel/plugins/nested_attributes.rb +1 -1
  104. data/lib/sequel/plugins/schema.rb +1 -1
  105. data/lib/sequel/plugins/single_table_inheritance.rb +7 -1
  106. data/lib/sequel/plugins/subset_conditions.rb +11 -3
  107. data/lib/sequel/plugins/whitelist_security.rb +118 -0
  108. data/lib/sequel/sql.rb +80 -36
  109. data/lib/sequel/timezones.rb +2 -0
  110. data/lib/sequel/version.rb +1 -1
  111. data/spec/adapters/mssql_spec.rb +20 -0
  112. data/spec/adapters/mysql_spec.rb +1 -1
  113. data/spec/adapters/oracle_spec.rb +12 -8
  114. data/spec/adapters/postgres_spec.rb +1 -1
  115. data/spec/adapters/spec_helper.rb +1 -1
  116. data/spec/adapters/sqlite_spec.rb +36 -34
  117. data/spec/core/connection_pool_spec.rb +2 -1
  118. data/spec/core/database_spec.rb +87 -9
  119. data/spec/core/dataset_spec.rb +501 -129
  120. data/spec/core/deprecated_spec.rb +1 -1
  121. data/spec/core/expression_filters_spec.rb +146 -60
  122. data/spec/core/mock_adapter_spec.rb +1 -1
  123. data/spec/core/object_graph_spec.rb +61 -9
  124. data/spec/core/placeholder_literalizer_spec.rb +20 -2
  125. data/spec/core/schema_generator_spec.rb +6 -6
  126. data/spec/core/schema_spec.rb +54 -5
  127. data/spec/core_extensions_spec.rb +122 -18
  128. data/spec/deprecation_helper.rb +27 -2
  129. data/spec/extensions/_deprecated_identifier_mangling_spec.rb +6 -6
  130. data/spec/extensions/association_proxies_spec.rb +2 -2
  131. data/spec/extensions/auto_literal_strings_spec.rb +212 -0
  132. data/spec/extensions/blacklist_security_spec.rb +1 -0
  133. data/spec/extensions/class_table_inheritance_spec.rb +1037 -39
  134. data/spec/extensions/column_select_spec.rb +20 -8
  135. data/spec/extensions/columns_introspection_spec.rb +3 -3
  136. data/spec/extensions/core_refinements_spec.rb +29 -12
  137. data/spec/extensions/dataset_associations_spec.rb +12 -12
  138. data/spec/extensions/def_dataset_method_spec.rb +100 -0
  139. data/spec/extensions/error_sql_spec.rb +1 -1
  140. data/spec/extensions/finder_spec.rb +260 -0
  141. data/spec/extensions/graph_each_spec.rb +2 -2
  142. data/spec/extensions/identifier_mangling_spec.rb +14 -8
  143. data/spec/extensions/inverted_subsets_spec.rb +4 -4
  144. data/spec/extensions/lazy_attributes_spec.rb +7 -0
  145. data/spec/extensions/many_through_many_spec.rb +38 -14
  146. data/spec/extensions/nested_attributes_spec.rb +18 -6
  147. data/spec/extensions/no_auto_literal_strings_spec.rb +1 -1
  148. data/spec/extensions/pg_enum_spec.rb +16 -1
  149. data/spec/extensions/pg_interval_spec.rb +11 -2
  150. data/spec/extensions/pg_loose_count_spec.rb +5 -0
  151. data/spec/extensions/pg_row_spec.rb +25 -0
  152. data/spec/extensions/prepared_statements_spec.rb +10 -1
  153. data/spec/extensions/query_spec.rb +2 -2
  154. data/spec/extensions/schema_dumper_spec.rb +2 -2
  155. data/spec/extensions/schema_spec.rb +2 -2
  156. data/spec/extensions/set_overrides_spec.rb +7 -3
  157. data/spec/extensions/sql_expr_spec.rb +0 -1
  158. data/spec/extensions/subset_conditions_spec.rb +6 -6
  159. data/spec/extensions/table_select_spec.rb +24 -12
  160. data/spec/extensions/to_dot_spec.rb +4 -4
  161. data/spec/extensions/whitelist_security_spec.rb +131 -0
  162. data/spec/integration/dataset_test.rb +9 -5
  163. data/spec/integration/model_test.rb +2 -0
  164. data/spec/integration/plugin_test.rb +2 -2
  165. data/spec/integration/spec_helper.rb +1 -1
  166. data/spec/model/associations_spec.rb +39 -11
  167. data/spec/model/base_spec.rb +44 -24
  168. data/spec/model/class_dataset_methods_spec.rb +18 -16
  169. data/spec/model/dataset_methods_spec.rb +4 -4
  170. data/spec/model/eager_loading_spec.rb +84 -24
  171. data/spec/model/model_spec.rb +97 -63
  172. data/spec/model/record_spec.rb +21 -13
  173. metadata +13 -2
@@ -67,4 +67,4 @@ describe "Sequel::Deprecated" do
67
67
  @output.first.must_equal 'foo'
68
68
  @output.count.must_equal 4
69
69
  end
70
- end
70
+ end if RUBY_VERSION >= '1.9'
@@ -17,13 +17,23 @@ describe "Blockless Ruby Filters" do
17
17
  @d.l(:x).must_equal 'x'
18
18
  end
19
19
 
20
- it "should support qualified columns and aliased columns using symbols" do
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
- it "should support qualified columns using virtual rows" do
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 = true
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, :x__y)).must_equal 'NOT is_blah(x.y)'
46
- @d.l(~Sequel.function(:is_blah, :x, :x__y)).must_equal 'NOT is_blah(x, x.y)'
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.expr(:a__y)).must_equal '(1.0 * a.y)'
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
- it "should return self on .lit" do
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
- it "should return have .sql_literal return the literal SQL for the expression" do
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
- db = Sequel.mock
505
- db.extend_datasets{}
506
- dsc = db.dataset_class
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
- it "should treat methods without arguments that have embedded double underscores as qualified identifiers" do
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
- it "should treat methods with a block and no arguments as a function call with no arguments" do
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 with a block and a leading argument :* as a function call with the SQL wildcard" do
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{}.*}.must_equal '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
- it "should treat methods with a block and a leading argument :distinct as a function call with DISTINCT and the additional method arguments" do
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
- it "should raise an error if an unsupported argument is used with a block" do
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
- it "should treat methods with a block and a leading argument :over as a window function call" do
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
- it "should support :partition options for window function calls" do
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
- it "should support :args options for window function calls" do
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
- it "should support :order option for window function calls" do
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
- it "should support :window option for window function calls" do
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
- it "should support :*=>true option for window function calls" do
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
- it "should support :frame=>:all option for window function calls" do
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
- it "should support :frame=>:rows option for window function calls" do
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
- it "should support :frame=>'some string' option for window function calls" do
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
- it "should raise an error if an invalid :frame option is used" do
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
- it "should support all these options together" do
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{}.over.over}}.must_raise(Sequel::Error)
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(:over, :* =>true, :partition=>a, :order=>b, :window=>:win, :frame=>:rows){}}}.must_raise(Sequel::Error)
643
- proc{Sequel.mock.dataset.filter{count(:over, :* =>true, :partition=>a, :order=>b, :window=>:win, :frame=>:rows){}}.sql}.must_raise(Sequel::Error)
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{}.lateral}.must_equal 'LATERAL 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{}.within_group(:a)}.must_equal 'mode() WITHIN GROUP (ORDER BY "a")'
652
- @d.l{mode{}.within_group(:a, :b)}.must_equal 'mode() WITHIN GROUP (ORDER BY "a", "b")'
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{}.*.filter(Sequel.&(:a, :b))}.must_equal 'count(*) FILTER (WHERE ("a" AND "b"))'
657
- @d.l{count{}.*.filter(:a=>1)}.must_equal 'count(*) FILTER (WHERE ("a" = 1))'
658
- @d.l{count{}.*.filter{b > 1}}.must_equal 'count(*) FILTER (WHERE ("b" > 1))'
659
- @d.l{count{}.*.filter(:a=>1){b > 1}}.must_equal 'count(*) FILTER (WHERE (("a" = 1) AND ("b" > 1)))'
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{}.within_group(:a).filter(:a=>1)}.must_equal 'mode() WITHIN GROUP (ORDER BY "a") FILTER (WHERE ("a" = 1))'
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{}.with_ordinality}.must_equal 'foo() WITH ORDINALITY'
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
- it "should support function method on qualified identifiers to create functions" do
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 handle quoted function names" do
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{}.quoted}.must_equal '"rank"()'
692
- @d.l{sch__rank{}.quoted}.must_equal '"sch__rank"()'
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
- it "should deal with methods added to Object after requiring Sequel" do
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
- it "should deal with private methods added to Kernel after requiring Sequel" do
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
- it "should have have ` produce literal strings" do
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{o__a} + 1, "(o.a + 1)")
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{o__a}) + 1, "(o.a + 1)")
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.expr(:a__b).*, 'a.b.*')
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')[:a___b].with_quote_identifiers(false).sql.must_equal "SELECT * FROM a AS 'b'"
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
- it "should accept a schema qualified symbolic table name as the dataset" do
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 "allows giving table alias in symbolic argument" do
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
- it "should handle a qualified identifier as the source" do
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
- it "should not add columns if graph is called after set_graph_aliases" do
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
- it "should not modify the current dataset's opts" do
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
- it "should only alias columns if necessary" do
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
- it "should not modify the current dataset's opts" do
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