sequel 5.11.0 → 5.12.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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +32 -0
  3. data/doc/advanced_associations.rdoc +132 -14
  4. data/doc/postgresql.rdoc +14 -0
  5. data/doc/release_notes/5.12.0.txt +141 -0
  6. data/lib/sequel/adapters/ado/mssql.rb +1 -1
  7. data/lib/sequel/adapters/oracle.rb +5 -6
  8. data/lib/sequel/adapters/postgres.rb +18 -5
  9. data/lib/sequel/adapters/shared/mysql.rb +5 -5
  10. data/lib/sequel/adapters/sqlite.rb +0 -5
  11. data/lib/sequel/adapters/tinytds.rb +0 -5
  12. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +2 -5
  13. data/lib/sequel/core.rb +6 -1
  14. data/lib/sequel/dataset/graph.rb +25 -9
  15. data/lib/sequel/dataset/placeholder_literalizer.rb +47 -17
  16. data/lib/sequel/dataset/prepared_statements.rb +86 -18
  17. data/lib/sequel/dataset/sql.rb +5 -1
  18. data/lib/sequel/extensions/caller_logging.rb +79 -0
  19. data/lib/sequel/extensions/constraint_validations.rb +1 -1
  20. data/lib/sequel/extensions/pg_static_cache_updater.rb +2 -2
  21. data/lib/sequel/model/associations.rb +56 -23
  22. data/lib/sequel/model/base.rb +3 -3
  23. data/lib/sequel/plugins/eager_graph_eager.rb +139 -0
  24. data/lib/sequel/plugins/static_cache.rb +9 -8
  25. data/lib/sequel/plugins/tactical_eager_loading.rb +63 -1
  26. data/lib/sequel/version.rb +1 -1
  27. data/spec/adapters/oracle_spec.rb +44 -0
  28. data/spec/adapters/postgres_spec.rb +39 -0
  29. data/spec/core/dataset_spec.rb +23 -9
  30. data/spec/core/object_graph_spec.rb +314 -284
  31. data/spec/extensions/caller_logging_spec.rb +52 -0
  32. data/spec/extensions/eager_graph_eager_spec.rb +100 -0
  33. data/spec/extensions/finder_spec.rb +1 -1
  34. data/spec/extensions/prepared_statements_spec.rb +7 -12
  35. data/spec/extensions/static_cache_spec.rb +14 -0
  36. data/spec/extensions/tactical_eager_loading_spec.rb +262 -1
  37. data/spec/integration/associations_test.rb +72 -0
  38. data/spec/integration/dataset_test.rb +3 -3
  39. data/spec/model/eager_loading_spec.rb +90 -0
  40. metadata +8 -2
@@ -6,7 +6,7 @@ module Sequel
6
6
 
7
7
  # The minor version of Sequel. Bumped for every non-patch level
8
8
  # release, generally around once a month.
9
- MINOR = 11
9
+ MINOR = 12
10
10
 
11
11
  # The tiny version of Sequel. Usually 0, only bumped for bugfix
12
12
  # releases that fix regressions from previous versions.
@@ -325,3 +325,47 @@ describe "An Oracle database with xml types" do
325
325
  DB.from(Sequel.lit('xml_test x')).select(Sequel.lit("x.xml_col.getCLOBVal() v")).all.must_equal [{:v=>"<a href=\"b\">c</a>\n"}]
326
326
  end
327
327
  end
328
+
329
+ describe "Clob Bound Argument Type" do
330
+ before(:all) do
331
+ @db = DB
332
+ @db.create_table!(:items) do
333
+ primary_key :id
334
+ clob :c
335
+ end
336
+ @ds = @db[:items]
337
+ end
338
+ before do
339
+ @ds.delete
340
+ end
341
+ after(:all) do
342
+ @db.drop_table?(:items)
343
+ end
344
+
345
+ it "should handle clob type in prepared statement arguments" do
346
+ @ds.delete
347
+ clob = "\"'[]`a0 "
348
+ @ds.prepare(:insert, :ps_clob, {:c=>@db.adapter_scheme == :oracle ? :$c__clob : :$c}).call(:c=>clob)
349
+ @ds.get(:c).must_equal clob
350
+ end
351
+ end
352
+
353
+ describe "CLOB Returning Procedure" do
354
+ before do
355
+ DB.run <<SQL
356
+ CREATE OR REPLACE PROCEDURE testCLOB(outParam OUT CLOB)
357
+ IS
358
+ BEGIN
359
+ outParam := 'Hello World CLOB OUT parameter';
360
+ END;
361
+ SQL
362
+ end
363
+ after do
364
+ DB.run("DROP PROCEDURE testCLOB")
365
+ end
366
+
367
+ it "should work correctly with output clobs" do
368
+ res = DB.execute("begin testCLOB(:1); end;", {:arguments => [[nil, 'clob']]}) {|c| c[1].read }
369
+ res.must_equal 'Hello World CLOB OUT parameter'
370
+ end
371
+ end if DB.adapter_scheme == :oracle
@@ -1239,6 +1239,45 @@ describe "A PostgreSQL database" do
1239
1239
  end if DB.server_version >= 90600
1240
1240
  end
1241
1241
 
1242
+ describe "Sequel::Postgres::Database" do
1243
+ before do
1244
+ @db = DB
1245
+ @db.create_table!(:posts){Integer :a}
1246
+ end
1247
+ after do
1248
+ @db.run("DROP PROCEDURE test_procedure_posts(int, int)")
1249
+ @db.drop_table?(:posts)
1250
+ end
1251
+
1252
+ it "#call_procedure should call a procedure that returns a row" do
1253
+ @db.run <<SQL
1254
+ CREATE OR REPLACE PROCEDURE test_procedure_posts(inout a int, inout b int)
1255
+ LANGUAGE SQL
1256
+ AS $$
1257
+ INSERT INTO posts VALUES (a) RETURNING *;
1258
+ INSERT INTO posts VALUES (a * 2) RETURNING *;
1259
+ SELECT max(posts.a), min(posts.a) FROM posts;
1260
+ $$;
1261
+ SQL
1262
+ @db.call_procedure(:test_procedure_posts, 1, nil).must_equal(:a=>2, :b=>1)
1263
+ @db.call_procedure(:test_procedure_posts, 3, nil).must_equal(:a=>6, :b=>1)
1264
+ end
1265
+
1266
+
1267
+ it "#call_procedure should call a procedure that doesn't return a row" do
1268
+ @db.run <<SQL
1269
+ CREATE OR REPLACE PROCEDURE test_procedure_posts(int, int)
1270
+ LANGUAGE SQL
1271
+ AS $$
1272
+ INSERT INTO posts VALUES ($1) RETURNING *;
1273
+ INSERT INTO posts VALUES ($1 * 2) RETURNING *;
1274
+ $$;
1275
+ SQL
1276
+ @db.call_procedure(:test_procedure_posts, 1, nil).must_be_nil
1277
+ @db.call_procedure(:test_procedure_posts, 3, nil).must_be_nil
1278
+ end
1279
+ end if DB.adapter_scheme == :postgres && DB.server_version >= 110000
1280
+
1242
1281
  describe "Postgres::Dataset#import" do
1243
1282
  before do
1244
1283
  @db = DB
@@ -3825,7 +3825,7 @@ end
3825
3825
  describe "Dataset prepared statements and bound variables " do
3826
3826
  before do
3827
3827
  @db = Sequel.mock
3828
- @ds = @db[:items].with_extend{def insert_select_sql(*v) "#{insert_sql(*v)} RETURNING *" end}
3828
+ @ds = @db[:items].with_extend{def insert_select_sql(*v) insert_sql(*v) << " RETURNING *" end}
3829
3829
  end
3830
3830
 
3831
3831
  it "#call should take a type and bind hash and interpolate it" do
@@ -3868,9 +3868,10 @@ describe "Dataset prepared statements and bound variables " do
3868
3868
  pss << @ds.filter(:num=>:$n).prepare(:delete, :dn)
3869
3869
  pss << @ds.filter(:num=>:$n).prepare(:update, :un, :num=>:$n2)
3870
3870
  pss << @ds.prepare(:insert, :in, :num=>:$n)
3871
+ pss << @ds.prepare(:insert_pk, :inp, :num=>:$n)
3871
3872
  pss << @ds.prepare(:insert_select, :ins, :num=>:$n)
3872
- @db.prepared_statements.keys.sort_by{|k| k.to_s}.must_equal [:ah, :dn, :en, :fn, :in, :ins, :sh, :shg, :sm, :sn, :un]
3873
- [:en, :sn, :sm, :ah, :sh, :shg, :fn, :dn, :un, :in, :ins].each_with_index{|x, i| @db.prepared_statements[x].must_equal pss[i]}
3873
+ @db.prepared_statements.keys.sort_by{|k| k.to_s}.must_equal [:ah, :dn, :en, :fn, :in, :inp, :ins, :sh, :shg, :sm, :sn, :un]
3874
+ [:en, :sn, :sm, :ah, :sh, :shg, :fn, :dn, :un, :in, :inp, :ins].each_with_index{|x, i| @db.prepared_statements[x].must_equal pss[i]}
3874
3875
  @db.call(:en, :n=>1){}
3875
3876
  @db.call(:sn, :n=>1)
3876
3877
  @db.call(:sm, :n=>1)
@@ -3881,6 +3882,7 @@ describe "Dataset prepared statements and bound variables " do
3881
3882
  @db.call(:dn, :n=>1)
3882
3883
  @db.call(:un, :n=>1, :n2=>2)
3883
3884
  @db.call(:in, :n=>1)
3885
+ @db.call(:inp, :n=>1)
3884
3886
  @db.call(:ins, :n=>1)
3885
3887
  @db.sqls.must_equal [
3886
3888
  'SELECT * FROM items WHERE (num = 1)',
@@ -3893,15 +3895,27 @@ describe "Dataset prepared statements and bound variables " do
3893
3895
  'DELETE FROM items WHERE (num = 1)',
3894
3896
  'UPDATE items SET num = 2 WHERE (num = 1)',
3895
3897
  'INSERT INTO items (num) VALUES (1)',
3898
+ 'INSERT INTO items (num) VALUES (1)',
3896
3899
  'INSERT INTO items (num) VALUES (1) RETURNING *']
3897
3900
  end
3898
3901
 
3902
+ it "should give correct results for recursive WITH" do
3903
+ ps = @ds.with_extend{def supports_cte?(type=nil) true end}.
3904
+ select(Sequel[:i].as(:id), Sequel[:pi].as(:parent_id)).
3905
+ with_recursive(:t, @ds.filter(:parent_id=>:$n), @ds.join(:t, :i=>:parent_id).filter(Sequel[:t][:i]=>:parent_id).
3906
+ select(Sequel[:i1][:id], Sequel[:i1][:parent_id]), :args=>[:i, :pi]).
3907
+ order(:id).
3908
+ prepare(:select, :cte_sel)
3909
+ ps.call(:n=>1).must_equal []
3910
+ @db.sqls.must_equal ["WITH t(i, pi) AS (SELECT * FROM items WHERE (parent_id = 1) UNION ALL SELECT i1.id, i1.parent_id FROM items INNER JOIN t ON (t.i = items.parent_id) WHERE (t.i = parent_id)) SELECT i AS id, pi AS parent_id FROM items ORDER BY id"]
3911
+ end
3912
+
3899
3913
  it "#call and #prepare should handle returning" do
3900
3914
  @ds = @ds.with_extend do
3901
3915
  def supports_returning?(_) true end
3902
- def insert_sql(*v) "#{super(*v)} RETURNING *" end
3903
- def update_sql(*v) "#{super(*v)} RETURNING *" end
3904
- def delete_sql; "#{super()} RETURNING *" end
3916
+ def insert_sql(*) super << " RETURNING *" end
3917
+ def update_sql(*) super << " RETURNING *" end
3918
+ def delete_sql; super << " RETURNING *" end
3905
3919
  end
3906
3920
  @ds = @ds.returning
3907
3921
  @ds.call(:insert, {:n=>1}, :num=>:$n)
@@ -4010,6 +4024,9 @@ describe Sequel::Dataset::UnnumberedArgumentMapper do
4010
4024
  def execute_insert(sql, opts={}, &block)
4011
4025
  super(sql, opts.merge({:arguments=>bind_arguments}), &block)
4012
4026
  end
4027
+ def prepared_statement_modules
4028
+ [Sequel::Dataset::UnnumberedArgumentMapper]
4029
+ end
4013
4030
  end
4014
4031
  @ps = []
4015
4032
  @ps << @ds.prepare(:select, :s)
@@ -4018,9 +4035,6 @@ describe Sequel::Dataset::UnnumberedArgumentMapper do
4018
4035
  @ps << @ds.prepare(:delete, :d)
4019
4036
  @ps << @ds.prepare(:insert, :i, :num=>:$n)
4020
4037
  @ps << @ds.prepare(:update, :u, :num=>:$n)
4021
- @ps.map! do |p|
4022
- p.with_extend(Sequel::Dataset::UnnumberedArgumentMapper)
4023
- end
4024
4038
  end
4025
4039
 
4026
4040
  it "#inspect should show the actual SQL submitted to the database" do
@@ -1,6 +1,6 @@
1
1
  require_relative "spec_helper"
2
2
 
3
- describe Sequel::Dataset, "graphing" do
3
+ describe Sequel::Dataset do
4
4
  before do
5
5
  @db = Sequel.mock(:columns=>proc do |sql|
6
6
  case sql
@@ -19,288 +19,318 @@ describe Sequel::Dataset, "graphing" do
19
19
  @db.sqls
20
20
  end
21
21
 
22
- describe "#graph" do
23
- it "should not modify the current dataset's opts" do
24
- o1 = @ds1.opts
25
- o2 = o1.dup
26
- ds1 = @ds1.graph(@ds2, :x=>:id)
27
- @ds1.opts.must_equal o1
28
- @ds1.opts.must_equal o2
29
- ds1.opts.wont_equal o1
30
- end
31
-
32
- it "should not modify the current dataset's opts if current dataset is already graphed" do
33
- ds2 = @ds1.graph(@ds2)
34
- @ds1.graph(@ds2)
35
- ds2.graph(@ds3)
36
- ds2.graph(@ds3)
37
- end
38
-
39
- it "should accept a simple dataset and pass the table to join" do
40
- ds = @ds1.graph(@ds2, :x=>:id)
41
- 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)'
42
- end
43
-
44
- it "should use currently selected columns as the basis for the selected columns in a new graph" do
45
- ds = @ds1.select(:id).graph(@ds2, :x=>:id)
46
- ds.sql.must_equal 'SELECT points.id, lines.id AS lines_id, lines.x, lines.y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
47
-
48
- ds = @ds1.select(:id, :x).graph(@ds2, :x=>:id)
49
- ds.sql.must_equal 'SELECT points.id, points.x, lines.id AS lines_id, lines.x AS lines_x, lines.y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
50
-
51
- ds = @ds1.select(Sequel.identifier(:id), Sequel.qualify(:points, :x)).graph(@ds2, :x=>:id)
52
- ds.sql.must_equal 'SELECT points.id, points.x, lines.id AS lines_id, lines.x AS lines_x, lines.y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
53
-
54
- ds = @ds1.select(Sequel.identifier(:id).qualify(:points), Sequel.identifier(:x).as(:y)).graph(@ds2, :x=>:id)
55
- ds.sql.must_equal 'SELECT points.id, points.x AS y, lines.id AS lines_id, lines.x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
56
-
57
- ds = @ds1.select(:id, Sequel.identifier(:x).qualify(Sequel.identifier(:points)).as(Sequel.identifier(:y))).graph(@ds2, :x=>:id)
58
- ds.sql.must_equal 'SELECT points.id, points.x AS y, lines.id AS lines_id, lines.x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
59
- end
60
-
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
67
- ds = @ds1.cross_join(:lines).select(:points__id, :lines__id___lid, :lines__x, :lines__y).graph(@ds3, :x=>:id)
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)'
69
- end
70
-
71
- it "should raise error if currently selected expressions cannot be handled" do
72
- proc{@ds1.select(1).graph(@ds2, :x=>:id)}.must_raise(Sequel::Error)
73
- end
74
-
75
- it "should accept a complex dataset and pass it directly to join" do
76
- ds = @ds1.graph(@ds2.select_all(:lines), {:x=>:id})
77
- 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)'
78
- end
79
-
80
- it "should accept a complex dataset and pass it directly to join" do
81
- ds = @ds1.graph(@ds2.filter(:x=>1), {:x=>:id})
82
- ds.sql.must_equal 'SELECT points.id, points.x, points.y, t1.id AS t1_id, t1.x AS t1_x, t1.y AS t1_y, t1.graph_id FROM points LEFT OUTER JOIN (SELECT * FROM lines WHERE (x = 1)) AS t1 ON (t1.x = points.id)'
83
- ds = @ds1.graph(@ds2.select_all(:lines).filter(:x=>1), {:x=>:id})
84
- ds.sql.must_equal 'SELECT points.id, points.x, points.y, t1.id AS t1_id, t1.x AS t1_x, t1.y AS t1_y, t1.graph_id FROM points LEFT OUTER JOIN (SELECT lines.* FROM lines WHERE (x = 1)) AS t1 ON (t1.x = points.id)'
85
- end
86
-
87
- it "should work on from_self datasets" do
88
- ds = @ds1.from_self.graph(@ds2, :x=>:id)
89
- ds.sql.must_equal 'SELECT t1.id, t1.x, t1.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM (SELECT * FROM points) AS t1 LEFT OUTER JOIN lines ON (lines.x = t1.id)'
90
- ds = @ds1.graph(@ds2.from_self, :x=>:id)
91
- ds.sql.must_equal 'SELECT points.id, points.x, points.y, t1.id AS t1_id, t1.x AS t1_x, t1.y AS t1_y, t1.graph_id FROM points LEFT OUTER JOIN (SELECT * FROM (SELECT * FROM lines) AS t1) AS t1 ON (t1.x = points.id)'
92
- ds = @ds1.from_self.from_self.graph(@ds2.from_self.from_self, :x=>:id)
93
- ds.sql.must_equal 'SELECT t1.id, t1.x, t1.y, t2.id AS t2_id, t2.x AS t2_x, t2.y AS t2_y, t2.graph_id FROM (SELECT * FROM (SELECT * FROM points) AS t1) AS t1 LEFT OUTER JOIN (SELECT * FROM (SELECT * FROM (SELECT * FROM lines) AS t1) AS t1) AS t2 ON (t2.x = t1.id)'
94
- ds = @ds1.from(@ds1, @ds3).graph(@ds2.from_self, :x=>:id)
95
- ds.sql.must_equal 'SELECT t1.id, t1.x, t1.y, t3.id AS t3_id, t3.x AS t3_x, t3.y AS t3_y, t3.graph_id FROM (SELECT * FROM (SELECT * FROM points) AS t1, (SELECT * FROM graphs) AS t2) AS t1 LEFT OUTER JOIN (SELECT * FROM (SELECT * FROM lines) AS t1) AS t3 ON (t3.x = t1.id)'
96
- end
97
-
98
- it "should accept a symbol table name as the dataset" do
99
- ds = @ds1.graph(:lines, :x=>:id)
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)'
101
- end
102
-
103
- with_symbol_splitting "should accept a schema qualified symbolic table name as the dataset" do
104
- ds = @ds1.graph(:schema__lines, :x=>:id)
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)'
106
- end
107
-
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
114
- ds = @ds1.graph(:lines___sketch, :x=>:id)
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)'
116
- ds = @ds1.graph(:schema__lines___sketch, :x=>:id)
117
- 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 schema.lines AS sketch ON (sketch.x = points.id)'
118
- end
119
-
120
- it "should accept a SQL::Identifier as the dataset" do
121
- ds = @ds1.graph(Sequel.identifier(:lines), :x=>:id)
122
- 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)'
123
- ds = @ds1.graph(Sequel.identifier('lines'), :x=>:id)
124
- 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 AS lines ON (lines.x = points.id)'
125
- end
126
-
127
- it "should handle a SQL::Identifier with double underscores correctly" do
128
- ds = @ds1.graph(Sequel.identifier(:lin__es), :x=>:id)
129
- ds.sql.must_equal 'SELECT points.id, points.x, points.y, lin__es.id AS lin__es_id, lin__es.name, lin__es.x AS lin__es_x, lin__es.y AS lin__es_y, lin__es.lines_x FROM points LEFT OUTER JOIN lin__es ON (lin__es.x = points.id)'
130
- ds = @ds1.from(Sequel.identifier(:poi__nts)).graph(Sequel.identifier(:lin__es), :x=>:id)
131
- ds.sql.must_equal 'SELECT poi__nts.id, poi__nts.name, poi__nts.x, poi__nts.y, poi__nts.lines_x, lin__es.id AS lin__es_id, lin__es.name AS lin__es_name, lin__es.x AS lin__es_x, lin__es.y AS lin__es_y, lin__es.lines_x AS lin__es_lines_x FROM poi__nts LEFT OUTER JOIN lin__es ON (lin__es.x = poi__nts.id)'
132
- ds = @ds1.from(Sequel.identifier(:poi__nts).qualify(:foo)).graph(Sequel.identifier(:lin__es).qualify(:bar), :x=>:id)
133
- ds.sql.must_equal 'SELECT foo.poi__nts.id, foo.poi__nts.x, foo.poi__nts.y, foo.poi__nts.graph_id, lin__es.id AS lin__es_id, lin__es.name, lin__es.x AS lin__es_x, lin__es.y AS lin__es_y, lin__es.lines_x FROM foo.poi__nts LEFT OUTER JOIN bar.lin__es AS lin__es ON (lin__es.x = foo.poi__nts.id)'
134
- end
135
-
136
- it "should accept a SQL::QualifiedIdentifier as the dataset" do
137
- ds = @ds1.graph(Sequel.qualify(:schema, :lines), :x=>:id)
138
- 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)'
139
- ds = @ds1.graph(Sequel.qualify('schema', 'lines'), :x=>:id)
140
- 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)'
141
- ds = @ds1.graph(Sequel.qualify(Sequel.identifier(:schema), Sequel.identifier(:lines)), :x=>:id)
142
- 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)'
143
- ds = @ds1.graph(Sequel.qualify(Sequel.identifier('schema'), Sequel.identifier('lines')), :x=>:id)
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)'
145
- end
146
-
147
- with_symbol_splitting "should handle a qualified identifier symbol as the source" do
148
- ds = @ds1.from(:schema__points).graph(:lines, :x=>:id)
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
153
- ds = @ds1.from(Sequel.qualify(:schema, :points)).graph(:lines, :x=>:id)
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)'
155
- end
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
-
162
- it "should accept a SQL::AliasedExpression as the dataset" do
163
- ds = @ds1.graph(Sequel.as(:lines, :foo), :x=>:id)
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)'
165
- ds = @ds1.graph(Sequel.as(Sequel.identifier(:lines), :foo), :x=>:id)
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)'
167
- ds = @ds1.graph(Sequel.as(Sequel.qualify(:schema, :lines), :foo), :x=>:id)
168
- 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)'
169
- end
170
-
171
- it "should raise an error if a symbol, dataset, or model is not used" do
172
- proc{@ds1.graph(Object.new, :x=>:id)}.must_raise(Sequel::Error)
173
- end
174
-
175
- it "should accept a :table_alias option" do
176
- ds = @ds1.graph(:lines, {:x=>:id}, :table_alias=>:planes)
177
- ds.sql.must_equal 'SELECT points.id, points.x, points.y, planes.id AS planes_id, planes.x AS planes_x, planes.y AS planes_y, planes.graph_id FROM points LEFT OUTER JOIN lines AS planes ON (planes.x = points.id)'
178
- end
179
-
180
- it "should accept a :implicit_qualifier option" do
181
- ds = @ds1.graph(:lines, {:x=>:id}, :implicit_qualifier=>:planes)
182
- 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 = planes.id)'
183
- end
184
-
185
- it "should accept a :join_type option" do
186
- ds = @ds1.graph(:lines, {:x=>:id}, :join_type=>:inner)
187
- 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 INNER JOIN lines ON (lines.x = points.id)'
188
- end
189
-
190
- it "should accept a :join_only option" do
191
- ds = @ds1.graph(:lines, {:x=>:id}, :join_only=>true)
192
- ds.sql.must_equal 'SELECT * FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
193
- end
194
-
195
- it "should not select any columns from the graphed table if :select option is false" do
196
- ds = @ds1.graph(:lines, {:x=>:id}, :select=>false).graph(:graphs, :id=>:graph_id)
197
- ds.sql.must_equal 'SELECT points.id, 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 points LEFT OUTER JOIN lines ON (lines.x = points.id) LEFT OUTER JOIN graphs ON (graphs.id = lines.graph_id)'
198
- end
199
-
200
- it "should use the given columns if :select option is used" do
201
- ds = @ds1.graph(:lines, {:x=>:id}, :select=>[:x, :graph_id]).graph(:graphs, :id=>:graph_id)
202
- ds.sql.must_equal 'SELECT points.id, points.x, points.y, lines.x AS lines_x, lines.graph_id, graphs.id AS graphs_id, graphs.name, graphs.x AS graphs_x, graphs.y AS graphs_y, graphs.lines_x AS graphs_lines_x FROM points LEFT OUTER JOIN lines ON (lines.x = points.id) LEFT OUTER JOIN graphs ON (graphs.id = lines.graph_id)'
203
- end
204
-
205
- it "should pass all join_conditions to join_table" do
206
- ds = @ds1.graph(@ds2, [[:x, :id], [:y, :id]])
207
- 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))'
208
- end
209
-
210
- it "should accept a block instead of conditions and pass it to join_table" do
211
- ds = @ds1.graph(@ds2){|ja, lja, js| [[Sequel.qualify(ja, :x), Sequel.qualify(lja, :id)], [Sequel.qualify(ja, :y), Sequel.qualify(lja, :id)]]}
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))'
213
- end
214
-
215
- it "should raise Error if set_graph_aliases is called on an ungraphed dataset" do
216
- proc{@ds1.set_graph_aliases([[:x,[:points, :x]], [:y,[:lines, :y]]])}.must_raise Sequel::Error
217
- end
218
-
219
- it "should allow graphing of multiple datasets" do
220
- ds = @ds1.graph(@ds2, :x=>:id).graph(@ds3, :id=>:graph_id)
221
- 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, graphs.id AS graphs_id, graphs.name, graphs.x AS graphs_x, graphs.y AS graphs_y, graphs.lines_x AS graphs_lines_x FROM points LEFT OUTER JOIN lines ON (lines.x = points.id) LEFT OUTER JOIN graphs ON (graphs.id = lines.graph_id)'
222
- end
223
-
224
- it "should allow graphing of the same dataset multiple times" do
225
- ds = @ds1.graph(@ds2, :x=>:id).graph(@ds2, {:y=>Sequel[:points][:id]}, :table_alias=>:graph)
226
- 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)'
227
- end
228
-
229
- with_symbol_splitting "should allow graphing of the same dataset multiple times when using splittable symbols" do
230
- ds = @ds1.graph(@ds2, :x=>:id).graph(@ds2, {:y=>:points__id}, :table_alias=>:graph)
231
- 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)'
232
- end
233
-
234
- it "should raise an error if the table/table alias has already been used" do
235
- proc{@ds1.graph(@ds1, :x=>:id)}.must_raise(Sequel::Error)
236
- @ds1.graph(@ds2, :x=>:id)
237
- proc{@ds1.graph(@ds2, :x=>:id).graph(@ds2, :x=>:id)}.must_raise(Sequel::Error)
238
- @ds1.graph(@ds2, :x=>:id).graph(@ds2, {:x=>:id}, :table_alias=>:blah)
239
- end
240
- end
241
-
242
- describe "#set_graph_aliases" do
243
- it "should not modify the current dataset's opts" do
244
- o1 = @ds1.opts
245
- o2 = o1.dup
246
- ds1 = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:graphs,:id])
247
- @ds1.opts.must_equal o1
248
- @ds1.opts.must_equal o2
249
- ds1.opts.wont_equal o1
250
- end
251
-
252
- it "should specify the graph mapping" do
253
- ds = @ds1.graph(:lines, :x=>:id)
254
- 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)'
255
- ds.set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y]).sql.must_equal 'SELECT points.x, lines.y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
256
- end
257
-
258
- it "should allow a third entry to specify an expression to use other than the default" do
259
- @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x, 1], :y=>[:lines, :y, Sequel.function(:random)]).sql.must_equal 'SELECT 1 AS x, random() AS y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
260
- end
261
-
262
- it "should allow a single array entry to specify a table, assuming the same column as the key" do
263
- @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points], :y=>[:lines]).sql.must_equal 'SELECT points.x, lines.y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
264
- end
265
-
266
- it "should allow hash values to be symbols specifying table, assuming the same column as the key" do
267
- @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>:points, :y=>:lines).sql.must_equal 'SELECT points.x, lines.y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
268
- end
269
-
270
- it "should only alias columns if necessary" do
271
- @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y]).sql.must_equal 'SELECT points.x, lines.y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
272
- end
273
-
274
- it "should only alias columns if necessary" do
275
- @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y]).sql.must_equal 'SELECT points.x, lines.y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
276
- @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x1=>[:points, :x], :y=>[:lines, :y]).sql.must_equal 'SELECT points.x AS x1, lines.y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
277
- end
278
- end
279
-
280
- describe "#add_graph_aliases" do
281
- it "should not modify the current dataset's opts" do
282
- ds1 = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:graphs,:id])
283
- o1 = ds1.opts
284
- o2 = o1.dup
285
- ds2 = ds1.add_graph_aliases(:y=>[:blah,:id])
286
- ds1.opts.must_equal o1
287
- ds1.opts.must_equal o2
288
- ds2.opts.wont_equal o1
289
- end
290
-
291
- it "should add columns to the graph mapping" do
292
- @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)'
293
- end
294
-
295
- it "should raise an error if called without existing graph aliases" do
296
- proc{@ds1.add_graph_aliases(:y=>[:lines, :r])}.must_raise(Sequel::Error)
297
- end
298
- end
299
-
300
- describe "#ungraphed" do
301
- it "should remove the splitting of result sets into component tables" do
302
- @db.fetch = {:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7}
303
- @ds1.graph(@ds2, :x=>:id).ungraphed.all.must_equal [{:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7}]
304
- end
22
+ it "#graph should not modify the current dataset's opts" do
23
+ o1 = @ds1.opts
24
+ o2 = o1.dup
25
+ ds1 = @ds1.graph(@ds2, :x=>:id)
26
+ @ds1.opts.must_equal o1
27
+ @ds1.opts.must_equal o2
28
+ ds1.opts.wont_equal o1
29
+ end
30
+
31
+ it "#graph should not modify the current dataset's opts if current dataset is already graphed" do
32
+ ds2 = @ds1.graph(@ds2)
33
+ @ds1.graph(@ds2)
34
+ ds2.graph(@ds3)
35
+ ds2.graph(@ds3)
36
+ end
37
+
38
+ it "#graph should accept a simple dataset and pass the table to join" do
39
+ ds = @ds1.graph(@ds2, :x=>:id)
40
+ 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)'
41
+ end
42
+
43
+ it "#graph should use currently selected columns as the basis for the selected columns in a new graph" do
44
+ ds = @ds1.select(:id).graph(@ds2, :x=>:id)
45
+ ds.sql.must_equal 'SELECT points.id, lines.id AS lines_id, lines.x, lines.y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
46
+
47
+ ds = @ds1.select(:id, :x).graph(@ds2, :x=>:id)
48
+ ds.sql.must_equal 'SELECT points.id, points.x, lines.id AS lines_id, lines.x AS lines_x, lines.y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
49
+
50
+ ds = @ds1.select(Sequel.identifier(:id), Sequel.qualify(:points, :x)).graph(@ds2, :x=>:id)
51
+ ds.sql.must_equal 'SELECT points.id, points.x, lines.id AS lines_id, lines.x AS lines_x, lines.y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
52
+
53
+ ds = @ds1.select(Sequel.identifier(:id).qualify(:points), Sequel.identifier(:x).as(:y)).graph(@ds2, :x=>:id)
54
+ ds.sql.must_equal 'SELECT points.id, points.x AS y, lines.id AS lines_id, lines.x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
55
+
56
+ ds = @ds1.select(:id, Sequel.identifier(:x).qualify(Sequel.identifier(:points)).as(Sequel.identifier(:y))).graph(@ds2, :x=>:id)
57
+ ds.sql.must_equal 'SELECT points.id, points.x AS y, lines.id AS lines_id, lines.x, lines.y AS lines_y, lines.graph_id FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
58
+ end
59
+
60
+ it "#graph should requalify currently selected columns in new graph if current dataset joins tables" do
61
+ ds = @ds1.cross_join(:lines).select(Sequel[:points][:id], Sequel[:lines][:id].as(:lid), Sequel[:lines][:x], Sequel[:lines][:y]).graph(@ds3, :x=>:id)
62
+ 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)'
63
+ end
64
+
65
+ with_symbol_splitting "#graph should requalify currently selected columns in new graph if current dataset joins tables with splittable symbols" do
66
+ ds = @ds1.cross_join(:lines).select(:points__id, :lines__id___lid, :lines__x, :lines__y).graph(@ds3, :x=>:id)
67
+ 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)'
68
+ end
69
+
70
+ it "#graph should handle selection expression without introspectable alias using a subselect" do
71
+ ds = @ds1.select(Sequel.lit('1 AS v'))
72
+ ds.columns :v
73
+ ds.graph(@ds2, :x=>:v).sql.must_equal "SELECT points.v, lines.id, lines.x, lines.y, lines.graph_id FROM (SELECT 1 AS v FROM points) AS points LEFT OUTER JOIN lines ON (lines.x = points.v)"
74
+ end
75
+
76
+ it "#graph should accept a complex dataset and pass it directly to join" do
77
+ ds = @ds1.graph(@ds2.select_all(:lines), {:x=>:id})
78
+ 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)'
79
+ end
80
+
81
+ it "#graph should accept a complex dataset and pass it directly to join" do
82
+ ds = @ds1.graph(@ds2.filter(:x=>1), {:x=>:id})
83
+ ds.sql.must_equal 'SELECT points.id, points.x, points.y, t1.id AS t1_id, t1.x AS t1_x, t1.y AS t1_y, t1.graph_id FROM points LEFT OUTER JOIN (SELECT * FROM lines WHERE (x = 1)) AS t1 ON (t1.x = points.id)'
84
+ ds = @ds1.graph(@ds2.select_all(:lines).filter(:x=>1), {:x=>:id})
85
+ ds.sql.must_equal 'SELECT points.id, points.x, points.y, t1.id AS t1_id, t1.x AS t1_x, t1.y AS t1_y, t1.graph_id FROM points LEFT OUTER JOIN (SELECT lines.* FROM lines WHERE (x = 1)) AS t1 ON (t1.x = points.id)'
86
+ end
87
+
88
+ it "#graph should work on from_self datasets" do
89
+ ds = @ds1.from_self.graph(@ds2, :x=>:id)
90
+ ds.sql.must_equal 'SELECT t1.id, t1.x, t1.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM (SELECT * FROM points) AS t1 LEFT OUTER JOIN lines ON (lines.x = t1.id)'
91
+ ds = @ds1.graph(@ds2.from_self, :x=>:id)
92
+ ds.sql.must_equal 'SELECT points.id, points.x, points.y, t1.id AS t1_id, t1.x AS t1_x, t1.y AS t1_y, t1.graph_id FROM points LEFT OUTER JOIN (SELECT * FROM (SELECT * FROM lines) AS t1) AS t1 ON (t1.x = points.id)'
93
+ ds = @ds1.from_self.from_self.graph(@ds2.from_self.from_self, :x=>:id)
94
+ ds.sql.must_equal 'SELECT t1.id, t1.x, t1.y, t2.id AS t2_id, t2.x AS t2_x, t2.y AS t2_y, t2.graph_id FROM (SELECT * FROM (SELECT * FROM points) AS t1) AS t1 LEFT OUTER JOIN (SELECT * FROM (SELECT * FROM (SELECT * FROM lines) AS t1) AS t1) AS t2 ON (t2.x = t1.id)'
95
+ ds = @ds1.from(@ds1, @ds3).graph(@ds2.from_self, :x=>:id)
96
+ ds.sql.must_equal 'SELECT t1.id, t1.x, t1.y, t3.id AS t3_id, t3.x AS t3_x, t3.y AS t3_y, t3.graph_id FROM (SELECT * FROM (SELECT * FROM points) AS t1, (SELECT * FROM graphs) AS t2) AS t1 LEFT OUTER JOIN (SELECT * FROM (SELECT * FROM lines) AS t1) AS t3 ON (t3.x = t1.id)'
97
+ end
98
+
99
+ it "#graph should accept a symbol table name as the dataset" do
100
+ ds = @ds1.graph(:lines, :x=>:id)
101
+ 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)'
102
+ end
103
+
104
+ with_symbol_splitting "#graph should accept a schema qualified symbolic table name as the dataset" do
105
+ ds = @ds1.graph(:schema__lines, :x=>:id)
106
+ 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)'
107
+ end
108
+
109
+ it "#graph should accept a qualified identifier table name as the dataset" do
110
+ ds = @ds1.graph(Sequel[:schema][:lines], :x=>:id)
111
+ 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)'
112
+ end
113
+
114
+ with_symbol_splitting "#graph allows giving table alias in symbolic argument" do
115
+ ds = @ds1.graph(:lines___sketch, :x=>:id)
116
+ 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)'
117
+ ds = @ds1.graph(:schema__lines___sketch, :x=>:id)
118
+ 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 schema.lines AS sketch ON (sketch.x = points.id)'
119
+ end
120
+
121
+ it "#graph should accept a SQL::Identifier as the dataset" do
122
+ ds = @ds1.graph(Sequel.identifier(:lines), :x=>:id)
123
+ 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)'
124
+ ds = @ds1.graph(Sequel.identifier('lines'), :x=>:id)
125
+ 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 AS lines ON (lines.x = points.id)'
126
+ end
127
+
128
+ it "#graph should handle a SQL::Identifier with double underscores correctly" do
129
+ ds = @ds1.graph(Sequel.identifier(:lin__es), :x=>:id)
130
+ ds.sql.must_equal 'SELECT points.id, points.x, points.y, lin__es.id AS lin__es_id, lin__es.name, lin__es.x AS lin__es_x, lin__es.y AS lin__es_y, lin__es.lines_x FROM points LEFT OUTER JOIN lin__es ON (lin__es.x = points.id)'
131
+ ds = @ds1.from(Sequel.identifier(:poi__nts)).graph(Sequel.identifier(:lin__es), :x=>:id)
132
+ ds.sql.must_equal 'SELECT poi__nts.id, poi__nts.name, poi__nts.x, poi__nts.y, poi__nts.lines_x, lin__es.id AS lin__es_id, lin__es.name AS lin__es_name, lin__es.x AS lin__es_x, lin__es.y AS lin__es_y, lin__es.lines_x AS lin__es_lines_x FROM poi__nts LEFT OUTER JOIN lin__es ON (lin__es.x = poi__nts.id)'
133
+ ds = @ds1.from(Sequel.identifier(:poi__nts).qualify(:foo)).graph(Sequel.identifier(:lin__es).qualify(:bar), :x=>:id)
134
+ ds.sql.must_equal 'SELECT foo.poi__nts.id, foo.poi__nts.x, foo.poi__nts.y, foo.poi__nts.graph_id, lin__es.id AS lin__es_id, lin__es.name, lin__es.x AS lin__es_x, lin__es.y AS lin__es_y, lin__es.lines_x FROM foo.poi__nts LEFT OUTER JOIN bar.lin__es AS lin__es ON (lin__es.x = foo.poi__nts.id)'
135
+ end
136
+
137
+ it "#graph should accept a SQL::QualifiedIdentifier as the dataset" do
138
+ ds = @ds1.graph(Sequel.qualify(:schema, :lines), :x=>:id)
139
+ 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)'
140
+ ds = @ds1.graph(Sequel.qualify('schema', 'lines'), :x=>:id)
141
+ 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)'
142
+ ds = @ds1.graph(Sequel.qualify(Sequel.identifier(:schema), Sequel.identifier(:lines)), :x=>:id)
143
+ 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)'
144
+ ds = @ds1.graph(Sequel.qualify(Sequel.identifier('schema'), Sequel.identifier('lines')), :x=>:id)
145
+ 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)'
146
+ end
147
+
148
+ with_symbol_splitting "#graph should handle a qualified identifier symbol as the source" do
149
+ ds = @ds1.from(:schema__points).graph(:lines, :x=>:id)
150
+ 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)'
151
+ end
152
+
153
+ it "#graph should handle a qualified identifier as the source" do
154
+ ds = @ds1.from(Sequel.qualify(:schema, :points)).graph(:lines, :x=>:id)
155
+ 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)'
156
+ end
157
+
158
+ with_symbol_splitting "#graph should accept a SQL::AliasedExpression with splittable symbol as the dataset" do
159
+ ds = @ds1.graph(Sequel.as(:schema__lines, :foo), :x=>:id)
160
+ 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)'
161
+ end
162
+
163
+ it "#graph should accept a SQL::AliasedExpression as the dataset" do
164
+ ds = @ds1.graph(Sequel.as(:lines, :foo), :x=>:id)
165
+ 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)'
166
+ ds = @ds1.graph(Sequel.as(Sequel.identifier(:lines), :foo), :x=>:id)
167
+ 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)'
168
+ ds = @ds1.graph(Sequel.as(Sequel.qualify(:schema, :lines), :foo), :x=>:id)
169
+ 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)'
170
+ end
171
+
172
+ it "#graph should raise an error if a symbol, dataset, or model is not used" do
173
+ proc{@ds1.graph(Object.new, :x=>:id)}.must_raise(Sequel::Error)
174
+ end
175
+
176
+ it "#graph should accept a :table_alias option" do
177
+ ds = @ds1.graph(:lines, {:x=>:id}, :table_alias=>:planes)
178
+ ds.sql.must_equal 'SELECT points.id, points.x, points.y, planes.id AS planes_id, planes.x AS planes_x, planes.y AS planes_y, planes.graph_id FROM points LEFT OUTER JOIN lines AS planes ON (planes.x = points.id)'
179
+ end
180
+
181
+ it "#graph should accept a :implicit_qualifier option" do
182
+ ds = @ds1.graph(:lines, {:x=>:id}, :implicit_qualifier=>:planes)
183
+ 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 = planes.id)'
184
+ end
185
+
186
+ it "#graph should accept a :join_type option" do
187
+ ds = @ds1.graph(:lines, {:x=>:id}, :join_type=>:inner)
188
+ 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 INNER JOIN lines ON (lines.x = points.id)'
189
+ end
190
+
191
+ it "#graph should accept a :join_only option" do
192
+ ds = @ds1.graph(:lines, {:x=>:id}, :join_only=>true)
193
+ ds.sql.must_equal 'SELECT * FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
194
+ end
195
+
196
+ it "#graph should not select any columns from the graphed table if :select option is false" do
197
+ ds = @ds1.graph(:lines, {:x=>:id}, :select=>false).graph(:graphs, :id=>:graph_id)
198
+ ds.sql.must_equal 'SELECT points.id, 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 points LEFT OUTER JOIN lines ON (lines.x = points.id) LEFT OUTER JOIN graphs ON (graphs.id = lines.graph_id)'
199
+ end
200
+
201
+ it "#graph should use the given columns if :select option is used" do
202
+ ds = @ds1.graph(:lines, {:x=>:id}, :select=>[:x, :graph_id]).graph(:graphs, :id=>:graph_id)
203
+ ds.sql.must_equal 'SELECT points.id, points.x, points.y, lines.x AS lines_x, lines.graph_id, graphs.id AS graphs_id, graphs.name, graphs.x AS graphs_x, graphs.y AS graphs_y, graphs.lines_x AS graphs_lines_x FROM points LEFT OUTER JOIN lines ON (lines.x = points.id) LEFT OUTER JOIN graphs ON (graphs.id = lines.graph_id)'
204
+ end
205
+
206
+ it "#graph should pass all join_conditions to join_table" do
207
+ ds = @ds1.graph(@ds2, [[:x, :id], [:y, :id]])
208
+ 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))'
209
+ end
210
+
211
+ it "#graph should accept a block instead of conditions and pass it to join_table" do
212
+ ds = @ds1.graph(@ds2){|ja, lja, js| [[Sequel.qualify(ja, :x), Sequel.qualify(lja, :id)], [Sequel.qualify(ja, :y), Sequel.qualify(lja, :id)]]}
213
+ 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))'
214
+ end
215
+
216
+ it "#graph should raise Error if set_graph_aliases is called on an ungraphed dataset" do
217
+ proc{@ds1.set_graph_aliases([[:x,[:points, :x]], [:y,[:lines, :y]]])}.must_raise Sequel::Error
218
+ end
219
+
220
+ it "#graph should allow graphing of multiple datasets" do
221
+ ds = @ds1.graph(@ds2, :x=>:id).graph(@ds3, :id=>:graph_id)
222
+ 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, graphs.id AS graphs_id, graphs.name, graphs.x AS graphs_x, graphs.y AS graphs_y, graphs.lines_x AS graphs_lines_x FROM points LEFT OUTER JOIN lines ON (lines.x = points.id) LEFT OUTER JOIN graphs ON (graphs.id = lines.graph_id)'
223
+ end
224
+
225
+ it "#graph should allow graphing of the same dataset multiple times" do
226
+ ds = @ds1.graph(@ds2, :x=>:id).graph(@ds2, {:y=>Sequel[:points][:id]}, :table_alias=>:graph)
227
+ 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)'
228
+ end
229
+
230
+ with_symbol_splitting "#graph should allow graphing of the same dataset multiple times when using splittable symbols" do
231
+ ds = @ds1.graph(@ds2, :x=>:id).graph(@ds2, {:y=>:points__id}, :table_alias=>:graph)
232
+ 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)'
233
+ end
234
+
235
+ it "#graph should raise an error if the table/table alias has already been used" do
236
+ proc{@ds1.graph(@ds1, :x=>:id)}.must_raise(Sequel::Error)
237
+ @ds1.graph(@ds2, :x=>:id)
238
+ proc{@ds1.graph(@ds2, :x=>:id).graph(@ds2, :x=>:id)}.must_raise(Sequel::Error)
239
+ @ds1.graph(@ds2, :x=>:id).graph(@ds2, {:x=>:id}, :table_alias=>:blah)
240
+ end
241
+
242
+ it "#graph should handle ColumnAll values in selections" do
243
+ @ds1.select_all(:points).graph(:lines, :x=>:id).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)"
244
+ @ds1.from{points}.select_all(:points).graph(:lines, :x=>:id).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)"
245
+ @ds1.select_all(:points).graph(:lines, :x=>:id).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)"
246
+ @ds1.from_self(:alias=>:p).select_all(:p).graph(:lines, :x=>:id).sql.must_equal "SELECT p.id, p.x, p.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM (SELECT * FROM points) AS p LEFT OUTER JOIN lines ON (lines.x = p.id)"
247
+ @ds1.from{points.as(p)}.select_all(:p).graph(:lines, :x=>:id).sql.must_equal "SELECT p.id, p.x, p.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM points AS p LEFT OUTER JOIN lines ON (lines.x = p.id)"
248
+ @ds1.from(Sequel[:s][:points]).select_all(Sequel[:s][:points]).graph(:lines, :x=>:id).sql.must_equal "SELECT s.points.id, s.points.x, s.points.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM s.points LEFT OUTER JOIN lines ON (lines.x = s.points.id)"
249
+ @ds1.from(Sequel[:s][:points].as(:p)).select_all(:p).graph(:lines, :x=>:id).sql.must_equal "SELECT p.id, p.x, p.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM s.points AS p LEFT OUTER JOIN lines ON (lines.x = p.id)"
250
+
251
+ @ds1.select_all('points').graph(:lines, :x=>:id).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)"
252
+ @ds1.from_self(:alias=>'p').select_all(:p).graph(:lines, :x=>:id).sql.must_equal "SELECT p.id, p.x, p.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM (SELECT * FROM points) AS p LEFT OUTER JOIN lines ON (lines.x = p.id)"
253
+
254
+ @ds1.select_all(Sequel.identifier('points')).graph(:lines, :x=>:id).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)"
255
+ @ds1.from_self(:alias=>Sequel.identifier(:p)).select_all(:p).graph(:lines, :x=>:id).sql.must_equal "SELECT p.id, p.x, p.y, lines.id AS lines_id, lines.x AS lines_x, lines.y AS lines_y, lines.graph_id FROM (SELECT * FROM points) AS p LEFT OUTER JOIN lines ON (lines.x = p.id)"
256
+
257
+ ds = @ds1.select_all(:points).select_append{(points[:id]+lines[:id]).as(:id2)}.join(:lines, :x=>:id)
258
+ ds.columns :id, :x, :y, :id2
259
+ ds.graph(:graphs, :id=>:graph_id).sql.must_equal "SELECT points.id, points.x, points.y, points.id2, graphs.id AS graphs_id, graphs.name, graphs.x AS graphs_x, graphs.y AS graphs_y, graphs.lines_x FROM (SELECT points.*, (points.id + lines.id) AS id2 FROM points INNER JOIN lines ON (lines.x = points.id)) AS points LEFT OUTER JOIN graphs ON (graphs.id = points.graph_id)"
260
+
261
+ ds = @ds1.select_all(:lines).select_append{(points[:id]+lines[:id]).as(:id2)}.join(:lines, :x=>:id)
262
+ ds.columns :id, :x, :y, :graph_id, :id2
263
+ ds.graph(:graphs, :id=>:graph_id).sql.must_equal "SELECT points.id, points.x, points.y, points.graph_id, points.id2, graphs.id AS graphs_id, graphs.name, graphs.x AS graphs_x, graphs.y AS graphs_y, graphs.lines_x FROM (SELECT lines.*, (points.id + lines.id) AS id2 FROM points INNER JOIN lines ON (lines.x = points.id)) AS points LEFT OUTER JOIN graphs ON (graphs.id = points.graph_id)"
264
+
265
+ ds = @ds1.select_all(:l).select_append{(points[:id]+lines[:id]).as(:id2)}.join(Sequel[:lines].as(:l), :x=>:id)
266
+ ds.columns :id, :x, :y, :graph_id, :id2
267
+ ds.graph(:graphs, :id=>:graph_id).sql.must_equal "SELECT points.id, points.x, points.y, points.graph_id, points.id2, graphs.id AS graphs_id, graphs.name, graphs.x AS graphs_x, graphs.y AS graphs_y, graphs.lines_x FROM (SELECT l.*, (points.id + lines.id) AS id2 FROM points INNER JOIN lines AS l ON (l.x = points.id)) AS points LEFT OUTER JOIN graphs ON (graphs.id = points.graph_id)"
268
+
269
+ ds = @ds1.select_all(:l).select_append{(points[:id]+lines[:id]).as(:id2)}.join(Sequel.as(:lines, :l), :x=>:id)
270
+ ds.columns :id, :x, :y, :graph_id, :id2
271
+ ds.graph(:graphs, :id=>:graph_id).sql.must_equal "SELECT points.id, points.x, points.y, points.graph_id, points.id2, graphs.id AS graphs_id, graphs.name, graphs.x AS graphs_x, graphs.y AS graphs_y, graphs.lines_x FROM (SELECT l.*, (points.id + lines.id) AS id2 FROM points INNER JOIN lines AS l ON (l.x = points.id)) AS points LEFT OUTER JOIN graphs ON (graphs.id = points.graph_id)"
272
+
273
+ ds = @ds1.select_all(:l).select_append{(points[:id]+lines[:id]).as(:id2)}.join(@ds1.db[:graphs].as(:l), :id=>:y)
274
+ ds.columns :id, :name, :x, :y, :lines_x, :id2
275
+ ds.graph(:lines, :x=>:id).sql.must_equal "SELECT points.id, points.name, points.x, points.y, points.lines_x, points.id2, lines.id AS lines_id, lines.x AS lines_x_0, lines.y AS lines_y, lines.graph_id FROM (SELECT l.*, (points.id + lines.id) AS id2 FROM points INNER JOIN (SELECT * FROM graphs) AS l ON (l.id = points.y)) AS points LEFT OUTER JOIN lines ON (lines.x = points.id)"
276
+ end
277
+
278
+ it "#set_graph_aliases should not modify the current dataset's opts" do
279
+ o1 = @ds1.opts
280
+ o2 = o1.dup
281
+ ds1 = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:graphs,:id])
282
+ @ds1.opts.must_equal o1
283
+ @ds1.opts.must_equal o2
284
+ ds1.opts.wont_equal o1
285
+ end
286
+
287
+ it "#set_graph_aliases should specify the graph mapping" do
288
+ ds = @ds1.graph(:lines, :x=>:id)
289
+ 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)'
290
+ ds.set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y]).sql.must_equal 'SELECT points.x, lines.y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
291
+ end
292
+
293
+ it "#set_graph_aliases should allow a third entry to specify an expression to use other than the default" do
294
+ @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x, 1], :y=>[:lines, :y, Sequel.function(:random)]).sql.must_equal 'SELECT 1 AS x, random() AS y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
295
+ end
296
+
297
+ it "#set_graph_aliases should allow a single array entry to specify a table, assuming the same column as the key" do
298
+ @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points], :y=>[:lines]).sql.must_equal 'SELECT points.x, lines.y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
299
+ end
300
+
301
+ it "#set_graph_aliases should allow hash values to be symbols specifying table, assuming the same column as the key" do
302
+ @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>:points, :y=>:lines).sql.must_equal 'SELECT points.x, lines.y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
303
+ end
304
+
305
+ it "#set_graph_aliases should only alias columns if necessary" do
306
+ @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y]).sql.must_equal 'SELECT points.x, lines.y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
307
+ end
308
+
309
+ it "#set_graph_aliases should only alias columns if necessary" do
310
+ @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y]).sql.must_equal 'SELECT points.x, lines.y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
311
+ @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x1=>[:points, :x], :y=>[:lines, :y]).sql.must_equal 'SELECT points.x AS x1, lines.y FROM points LEFT OUTER JOIN lines ON (lines.x = points.id)'
312
+ end
313
+
314
+ it "#add_graph_aliases should not modify the current dataset's opts" do
315
+ ds1 = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:graphs,:id])
316
+ o1 = ds1.opts
317
+ o2 = o1.dup
318
+ ds2 = ds1.add_graph_aliases(:y=>[:blah,:id])
319
+ ds1.opts.must_equal o1
320
+ ds1.opts.must_equal o2
321
+ ds2.opts.wont_equal o1
322
+ end
323
+
324
+ it "#add_graph_aliases should add columns to the graph mapping" do
325
+ @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)'
326
+ end
327
+
328
+ it "#add_graph_aliases should raise an error if called without existing graph aliases" do
329
+ proc{@ds1.add_graph_aliases(:y=>[:lines, :r])}.must_raise(Sequel::Error)
330
+ end
331
+
332
+ it "#ungraphed should remove the splitting of result sets into component tables" do
333
+ @db.fetch = {:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7}
334
+ @ds1.graph(@ds2, :x=>:id).ungraphed.all.must_equal [{:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7}]
305
335
  end
306
336
  end