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.
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