sequel 5.11.0 → 5.12.0

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