sequel 4.39.0 → 4.40.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +34 -0
  3. data/README.rdoc +8 -4
  4. data/doc/active_record.rdoc +1 -1
  5. data/doc/advanced_associations.rdoc +7 -7
  6. data/doc/association_basics.rdoc +7 -7
  7. data/doc/cheat_sheet.rdoc +5 -3
  8. data/doc/core_extensions.rdoc +3 -3
  9. data/doc/dataset_filtering.rdoc +1 -1
  10. data/doc/object_model.rdoc +16 -7
  11. data/doc/postgresql.rdoc +3 -3
  12. data/doc/querying.rdoc +3 -3
  13. data/doc/release_notes/4.40.0.txt +179 -0
  14. data/doc/security.rdoc +2 -1
  15. data/doc/sql.rdoc +34 -18
  16. data/doc/testing.rdoc +1 -0
  17. data/doc/virtual_rows.rdoc +11 -2
  18. data/lib/sequel/adapters/jdbc/derby.rb +7 -1
  19. data/lib/sequel/adapters/jdbc/h2.rb +15 -1
  20. data/lib/sequel/adapters/oracle.rb +9 -5
  21. data/lib/sequel/adapters/postgres.rb +0 -1
  22. data/lib/sequel/adapters/shared/cubrid.rb +11 -11
  23. data/lib/sequel/adapters/shared/db2.rb +4 -8
  24. data/lib/sequel/adapters/shared/mssql.rb +41 -28
  25. data/lib/sequel/adapters/shared/mysql.rb +9 -6
  26. data/lib/sequel/adapters/shared/oracle.rb +16 -5
  27. data/lib/sequel/adapters/shared/postgres.rb +84 -45
  28. data/lib/sequel/adapters/shared/sqlanywhere.rb +29 -15
  29. data/lib/sequel/adapters/shared/sqlite.rb +6 -6
  30. data/lib/sequel/core.rb +61 -10
  31. data/lib/sequel/database/connecting.rb +2 -1
  32. data/lib/sequel/database/features.rb +7 -0
  33. data/lib/sequel/database/query.rb +1 -1
  34. data/lib/sequel/database/schema_methods.rb +30 -3
  35. data/lib/sequel/database/transactions.rb +4 -2
  36. data/lib/sequel/dataset/actions.rb +1 -1
  37. data/lib/sequel/dataset/graph.rb +6 -1
  38. data/lib/sequel/dataset/query.rb +14 -7
  39. data/lib/sequel/dataset/sql.rb +2 -2
  40. data/lib/sequel/extensions/core_extensions.rb +2 -1
  41. data/lib/sequel/extensions/pg_row.rb +2 -2
  42. data/lib/sequel/extensions/s.rb +57 -0
  43. data/lib/sequel/extensions/set_overrides.rb +5 -1
  44. data/lib/sequel/extensions/sql_expr.rb +1 -0
  45. data/lib/sequel/extensions/symbol_aref.rb +71 -0
  46. data/lib/sequel/extensions/symbol_aref_refinement.rb +41 -0
  47. data/lib/sequel/extensions/symbol_as.rb +23 -0
  48. data/lib/sequel/extensions/symbol_as_refinement.rb +35 -0
  49. data/lib/sequel/model/base.rb +3 -3
  50. data/lib/sequel/plugins/class_table_inheritance.rb +14 -3
  51. data/lib/sequel/plugins/column_select.rb +4 -2
  52. data/lib/sequel/plugins/dataset_associations.rb +12 -4
  53. data/lib/sequel/plugins/insert_returning_select.rb +1 -1
  54. data/lib/sequel/plugins/mssql_optimistic_locking.rb +1 -1
  55. data/lib/sequel/plugins/prepared_statements.rb +1 -0
  56. data/lib/sequel/sql.rb +40 -8
  57. data/lib/sequel/version.rb +1 -1
  58. data/spec/adapters/firebird_spec.rb +3 -3
  59. data/spec/adapters/mssql_spec.rb +40 -40
  60. data/spec/adapters/mysql_spec.rb +5 -5
  61. data/spec/adapters/oracle_spec.rb +4 -4
  62. data/spec/adapters/postgres_spec.rb +135 -124
  63. data/spec/adapters/spec_helper.rb +1 -0
  64. data/spec/adapters/sqlite_spec.rb +6 -6
  65. data/spec/core/dataset_spec.rb +2 -2
  66. data/spec/core/expression_filters_spec.rb +43 -2
  67. data/spec/core/schema_spec.rb +35 -1
  68. data/spec/core_extensions_spec.rb +27 -0
  69. data/spec/extensions/class_table_inheritance_spec.rb +8 -0
  70. data/spec/extensions/column_select_spec.rb +8 -0
  71. data/spec/extensions/core_refinements_spec.rb +1 -1
  72. data/spec/extensions/dataset_associations_spec.rb +9 -0
  73. data/spec/extensions/insert_returning_select_spec.rb +20 -0
  74. data/spec/extensions/prepared_statements_spec.rb +7 -0
  75. data/spec/extensions/s_spec.rb +60 -0
  76. data/spec/extensions/symbol_aref_refinement_spec.rb +28 -0
  77. data/spec/extensions/symbol_as_refinement_spec.rb +21 -0
  78. data/spec/integration/associations_test.rb +62 -57
  79. data/spec/integration/dataset_test.rb +54 -54
  80. data/spec/integration/eager_loader_test.rb +7 -7
  81. data/spec/integration/plugin_test.rb +20 -20
  82. data/spec/integration/prepared_statement_test.rb +1 -1
  83. data/spec/integration/schema_test.rb +21 -0
  84. data/spec/integration/spec_helper.rb +1 -0
  85. metadata +12 -2
@@ -0,0 +1,23 @@
1
+ # frozen-string-literal: true
2
+ #
3
+ # The symbol_as extension adds Symbol#as, for creating
4
+ # Sequel::SQL::AliasedExpression objects. It's
5
+ # designed as a shortcut so that instead of:
6
+ #
7
+ # Sequel[:column].as(:alias)
8
+ #
9
+ # you can just write:
10
+ #
11
+ # :column.as(:alias)
12
+ #
13
+ # To load the extension:
14
+ #
15
+ # Sequel.extension :symbol_as
16
+ #
17
+ # If you are using Ruby 2+, and you would like to use refinements, there
18
+ # is a refinement version of this in the symbol_as_refinement extension.
19
+
20
+ #
21
+ class Symbol
22
+ include Sequel::SQL::AliasMethods
23
+ end
@@ -0,0 +1,35 @@
1
+ # frozen-string-literal: true
2
+ #
3
+ # The symbol_as_refinement extension adds a refinement that makes
4
+ # Symbol#as return Sequel::SQL::AliasedExpression instances. It's
5
+ # designed as a shortcut so that instead of:
6
+ #
7
+ # Sequel[:column].as(:alias) # column AS alias
8
+ #
9
+ # you can just write:
10
+ #
11
+ # :column.as(:alias) # column AS alias
12
+ #
13
+ # To load the extension:
14
+ #
15
+ # Sequel.extension :symbol_as_refinement
16
+ #
17
+ # To enable the refinement for the current file:
18
+ #
19
+ # using Sequel::SymbolAs
20
+ #
21
+ # If you would like this extension to be enabled globally instead
22
+ # of as a refinement, use the symbol_as extension.
23
+ #
24
+ # Related module: Sequel::SymbolAs
25
+
26
+ raise(Sequel::Error, "Refinements require ruby 2.0.0 or greater") unless RUBY_VERSION >= '2.0.0'
27
+
28
+ module Sequel::SymbolAs
29
+ refine Symbol do
30
+ def as(aliaz, columns=nil)
31
+ Sequel::SQL::AliasedExpression.new(self, aliaz, columns)
32
+ end
33
+ end
34
+ end
35
+
@@ -1614,12 +1614,12 @@ module Sequel
1614
1614
  model.primary_key_hash(pk)
1615
1615
  end
1616
1616
 
1617
- # Returns a hash mapping the receivers primary key column(s) to their values.
1617
+ # Returns a hash mapping the receivers qualified primary key column(s) to their values.
1618
1618
  #
1619
1619
  # Artist[1].qualified_pk_hash
1620
- # # => {Sequel.qualify(:artists, :id)=>1}
1620
+ # # => {Sequel[:artists][:id]=>1}
1621
1621
  # Artist[[1, 2]].qualified_pk_hash
1622
- # # => {Sequel.qualify(:artists, :id1)=>1, Sequel.qualify(:artists, :id2)=>2}
1622
+ # # => {Sequel[:artists][:id1]=>1, Sequel[:artists][:id2]=>2}
1623
1623
  def qualified_pk_hash(qualifier=model.table_name)
1624
1624
  model.qualified_primary_key_hash(pk, qualifier)
1625
1625
  end
@@ -31,9 +31,15 @@ module Sequel
31
31
  # The class_table_inheritance plugin assumes that the root table
32
32
  # (e.g. employees) has a primary key column (usually autoincrementing),
33
33
  # and all other tables have a foreign key of the same name that points
34
- # to the same column in their superclass's table. In this example,
35
- # the employees id column is a primary key and the id column in every
36
- # other table is a foreign key referencing the employees id.
34
+ # to the same column in their superclass's table, which is also the primary
35
+ # key for that table. In this example, the employees table has an id column
36
+ # is a primary key and the id column in every other table is a foreign key
37
+ # referencing employees.id, which is also the primary key of that table.
38
+ #
39
+ # Additionally, note that other than the primary key column, no subclass
40
+ # table has a column with the same name as any superclass table. This plugin
41
+ # does not support cases where the column names in a subclass table overlap
42
+ # with any column names in a superclass table.
37
43
  #
38
44
  # In this example the staff table also stores Cook model objects and the
39
45
  # executives table also stores CEO model objects.
@@ -354,6 +360,11 @@ module Sequel
354
360
  cti_this(m).update(h) unless h.empty?
355
361
  end
356
362
  end
363
+
364
+ # Don't allow use of prepared statements.
365
+ def use_prepared_statements_for?(type)
366
+ false
367
+ end
357
368
  end
358
369
  end
359
370
  end
@@ -48,8 +48,10 @@ module Sequel
48
48
  cols = cols.map{|c, _| c}
49
49
  end
50
50
  end
51
- cols ||= check_non_connection_error{ds.columns}
52
- ds = ds.select(*cols.map{|c| Sequel.qualify(ds.first_source, Sequel.identifier(c))})
51
+
52
+ if cols ||= check_non_connection_error{ds.columns}
53
+ ds = ds.select(*cols.map{|c| Sequel.qualify(ds.first_source, Sequel.identifier(c))})
54
+ end
53
55
  end
54
56
  ds
55
57
  end
@@ -93,12 +93,20 @@ module Sequel
93
93
  where(r.qualify(r.join_table_alias, r[:left_keys])=>sds.select(*r.qualify(model.table_name, r[:left_primary_key_columns])))
94
94
  ds.filter(r.qualified_right_primary_key=>r.send(:apply_filter_by_associations_limit_strategy, mds))
95
95
  when :many_through_many, :one_through_many
96
- fre = r.reverse_edges.first
97
96
  fe, *edges = r.edges
98
97
  edges << r.final_edge
99
- mds = model.
100
- select(*Array(r.qualify(fre[:table], fre[:left]))).
101
- join(fe[:table], Array(fe[:right]).zip(Array(fe[:left])), :implicit_qualifier=>model.table_name).
98
+ if fre = r.reverse_edges.first
99
+ table = fre[:table]
100
+ left = fre[:left]
101
+ mds = model.join(fe[:table], Array(fe[:right]).zip(Array(fe[:left])), :implicit_qualifier=>model.table_name)
102
+ else
103
+ table = fe[:table]
104
+ left = edges.first[:left]
105
+ edges = []
106
+ mds = r.associated_dataset
107
+ end
108
+ mds = mds.
109
+ select(*Array(r.qualify(table, left))).
102
110
  where(r.qualify(fe[:table], fe[:right])=>sds.select(*r.qualify(model.table_name, r[:left_primary_key_columns])))
103
111
  edges.each{|e| mds = mds.join(e[:table], Array(e[:right]).zip(Array(e[:left])))}
104
112
  ds.filter(r.qualified_right_primary_key=>r.send(:apply_filter_by_associations_limit_strategy, mds))
@@ -35,7 +35,7 @@ module Sequel
35
35
  # When reseting the instance dataset, also reset the instance_insert_dataset.
36
36
  def reset_instance_dataset
37
37
  ret = super
38
- ds = @instance_dataset
38
+ return unless ds = @instance_dataset
39
39
 
40
40
  if columns = insert_returning_columns(ds)
41
41
  ds = ds.returning(*columns)
@@ -84,7 +84,7 @@ module Sequel
84
84
  def _update_without_checking(columns)
85
85
  ds = _update_dataset
86
86
  lc = model.lock_column
87
- rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.output(nil, [Sequel.qualify(:inserted, lc)]).update_sql(columns))).all
87
+ rows = ds.clone(ds.send(:default_server_opts, :sql=>ds.output(nil, [Sequel[:inserted][lc]]).update_sql(columns))).all
88
88
  values[lc] = rows.first[lc] unless rows.empty?
89
89
  rows.length
90
90
  end
@@ -134,6 +134,7 @@ module Sequel
134
134
 
135
135
  # Use a prepared statement to query the database for the row matching the given primary key.
136
136
  def primary_key_lookup(pk)
137
+ return super if dataset.joined_dataset?
137
138
  prepared_lookup.call(primary_key_hash(pk))
138
139
  end
139
140
 
@@ -206,6 +206,9 @@ module Sequel
206
206
  # Operator symbols that take one or more arguments
207
207
  N_ARITY_OPERATORS = [:AND, :OR, :'||'] + MATHEMATICAL_OPERATORS + BITWISE_OPERATORS - [:**]
208
208
 
209
+ # Operator symbols that are associative
210
+ ASSOCIATIVE_OPERATORS = [:AND, :OR, :'||', :+, :*, :&, :|]
211
+
209
212
  # Operator symbols that take only a single argument
210
213
  ONE_ARITY_OPERATORS = [:NOT, :NOOP, :'B~']
211
214
 
@@ -229,9 +232,12 @@ module Sequel
229
232
  case op
230
233
  when *N_ARITY_OPERATORS
231
234
  raise(Error, "The #{op} operator requires at least 1 argument") unless args.length >= 1
232
- old_args = args.map{|a| a.is_a?(self.class) && a.op == :NOOP ? a.args.first : a}
233
- args = []
234
- old_args.each{|a| a.is_a?(self.class) && a.op == op ? args.concat(a.args) : args.push(a)}
235
+ args.map!{|a| a.is_a?(self.class) && a.op == :NOOP ? a.args.first : a}
236
+ if ASSOCIATIVE_OPERATORS.include?(op)
237
+ old_args = args
238
+ args = []
239
+ old_args.each{|a| a.is_a?(self.class) && a.op == op ? args.concat(a.args) : args.push(a)}
240
+ end
235
241
  when *TWO_ARITY_OPERATORS
236
242
  raise(Error, "The #{op} operator requires precisely 2 arguments") unless args.length == 2
237
243
  # With IN/NOT IN, even if the second argument is an array of two element arrays,
@@ -944,12 +950,21 @@ module Sequel
944
950
 
945
951
  # Qualify the receiver with the given +qualifier+ (table for column/schema for table).
946
952
  #
947
- # Sequel[:column].qualify(:table) # "table"."column"
948
- # Sequel[:table].qualify(:schema) # "schema"."table"
953
+ # Sequel[:column].qualify(:table) # "table"."column"
954
+ # Sequel[:table].qualify(:schema) # "schema"."table"
949
955
  # Sequel.qualify(:table, :column).qualify(:schema) # "schema"."table"."column"
950
956
  def qualify(qualifier)
951
957
  QualifiedIdentifier.new(qualifier, self)
952
958
  end
959
+
960
+ # Qualify the receiver with the given +qualifier+ (table for column/schema for table).
961
+ #
962
+ # Sequel[:table][:column] # "table"."column"
963
+ # Sequel[:schema][:table] # "schema"."table"
964
+ # Sequel[:schema][:table][:column] # "schema"."table"."column"
965
+ def [](identifier)
966
+ QualifiedIdentifier.new(self, identifier)
967
+ end
953
968
  end
954
969
 
955
970
  # This module includes the +like+ and +ilike+ methods used for pattern matching that are defined on objects that can be
@@ -1635,7 +1650,8 @@ module Sequel
1635
1650
 
1636
1651
  # Set the table and column to the given arguments
1637
1652
  def initialize(table, column)
1638
- @table, @column = table, column
1653
+ @table = convert_identifier(table)
1654
+ @column = convert_identifier(column)
1639
1655
  end
1640
1656
 
1641
1657
  # Create a Function using this identifier as the functions name, with
@@ -1645,6 +1661,18 @@ module Sequel
1645
1661
  end
1646
1662
 
1647
1663
  to_s_method :qualified_identifier_sql, "@table, @column"
1664
+
1665
+ private
1666
+
1667
+ # Automatically convert SQL::Identifiers to strings
1668
+ def convert_identifier(identifier)
1669
+ case identifier
1670
+ when SQL::Identifier
1671
+ identifier.value.to_s
1672
+ else
1673
+ identifier
1674
+ end
1675
+ end
1648
1676
  end
1649
1677
 
1650
1678
  # Subclass of +ComplexExpression+ where the expression results
@@ -1869,8 +1897,12 @@ module Sequel
1869
1897
  end
1870
1898
  end
1871
1899
  elsif args.empty?
1872
- table, column = m.to_s.split(DOUBLE_UNDERSCORE, 2)
1873
- column ? QualifiedIdentifier.new(table, column) : Identifier.new(m)
1900
+ if Sequel.split_symbols?
1901
+ table, column = m.to_s.split(DOUBLE_UNDERSCORE, 2)
1902
+ column ? QualifiedIdentifier.new(table, column) : Identifier.new(m)
1903
+ else
1904
+ Identifier.new(m)
1905
+ end
1874
1906
  else
1875
1907
  Function.new(m, *args)
1876
1908
  end
@@ -5,7 +5,7 @@ module Sequel
5
5
  MAJOR = 4
6
6
  # The minor version of Sequel. Bumped for every non-patch level
7
7
  # release, generally around once a month.
8
- MINOR = 39
8
+ MINOR = 40
9
9
  # The tiny version of Sequel. Usually 0, only bumped for bugfix
10
10
  # releases that fix regressions from previous versions.
11
11
  TINY = 0
@@ -125,7 +125,7 @@ describe "A Firebird dataset" do
125
125
  @d.select(:now[]).sql.must_equal \
126
126
  'SELECT now() FROM "TEST"'
127
127
 
128
- @d.select(:max[:items__val]).sql.must_equal \
128
+ @d.select(:max[Sequel[:items][:val]]).sql.must_equal \
129
129
  'SELECT max("ITEMS"."VAL") FROM "TEST"'
130
130
 
131
131
  @d.order(:name.desc).sql.must_equal \
@@ -143,10 +143,10 @@ describe "A Firebird dataset" do
143
143
  @d.select(:test[:ABC, 'hello']).sql.must_equal \
144
144
  "SELECT test(\"ABC\", 'hello') FROM \"TEST\""
145
145
 
146
- @d.select(:test[:ABC__DEF, 'hello']).sql.must_equal \
146
+ @d.select(:test[Sequel[:ABC][:DEF], 'hello']).sql.must_equal \
147
147
  "SELECT test(\"ABC\".\"DEF\", 'hello') FROM \"TEST\""
148
148
 
149
- @d.select(:test[:ABC__DEF, 'hello'].as(:X2)).sql.must_equal \
149
+ @d.select(:test[Sequel[:ABC][:DEF], 'hello'].as(:X2)).sql.must_equal \
150
150
  "SELECT test(\"ABC\".\"DEF\", 'hello') AS \"X2\" FROM \"TEST\""
151
151
 
152
152
  @d.insert_sql(:val => 333).must_match \
@@ -62,11 +62,11 @@ describe "MSSQL" do
62
62
  end
63
63
 
64
64
  it "should should support CROSS APPLY" do
65
- @db[:test3].cross_apply(@db[:test4].where(:test3__v3=>:test4__v4)).select_order_map([:v3, :v4]).must_equal [[1,1]]
65
+ @db[:test3].cross_apply(@db[:test4].where(Sequel[:test3][:v3]=>Sequel[:test4][:v4])).select_order_map([:v3, :v4]).must_equal [[1,1]]
66
66
  end
67
67
 
68
68
  it "should should support OUTER APPLY" do
69
- @db[:test3].outer_apply(@db[:test4].where(:test3__v3=>:test4__v4)).select_order_map([:v3, :v4]).must_equal [[1,1], [2, nil]]
69
+ @db[:test3].outer_apply(@db[:test4].where(Sequel[:test3][:v3]=>Sequel[:test4][:v4])).select_order_map([:v3, :v4]).must_equal [[1,1], [2, nil]]
70
70
  end
71
71
  end
72
72
 
@@ -105,7 +105,7 @@ describe "MSSQL Dataset#join_table" do
105
105
  ['SELECT * FROM [ITEMS] INNER JOIN [CATEGORIES] ON (([CATEGORIES].[ID1] = [ITEMS].[ID1]) AND ([CATEGORIES].[ID2] = [ITEMS].[ID2]))',
106
106
  'SELECT * FROM [ITEMS] INNER JOIN [CATEGORIES] ON (([CATEGORIES].[ID2] = [ITEMS].[ID2]) AND ([CATEGORIES].[ID1] = [ITEMS].[ID1]))'].
107
107
  must_include(DB[:items].join(:categories, [:id1, :id2]).sql)
108
- DB[:items___i].join(:categories___c, [:id]).sql.must_equal 'SELECT * FROM [ITEMS] AS [I] INNER JOIN [CATEGORIES] AS [C] ON ([C].[ID] = [I].[ID])'
108
+ DB[Sequel[:items].as(:i)].join(Sequel[:categories].as(:c), [:id]).sql.must_equal 'SELECT * FROM [ITEMS] AS [I] INNER JOIN [CATEGORIES] AS [C] ON ([C].[ID] = [I].[ID])'
109
109
  end
110
110
  end
111
111
 
@@ -121,56 +121,56 @@ describe "MSSQL Dataset#output" do
121
121
  end
122
122
 
123
123
  it "should format OUTPUT clauses without INTO for DELETE statements" do
124
- @ds.output(nil, [:deleted__name, :deleted__value]).delete_sql.must_match(/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\]/)
124
+ @ds.output(nil, [Sequel[:deleted][:name], Sequel[:deleted][:value]]).delete_sql.must_match(/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\]/)
125
125
  @ds.output(nil, [Sequel::SQL::ColumnAll.new(:deleted)]).delete_sql.must_match(/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].*/)
126
126
  end
127
127
 
128
128
  it "should format OUTPUT clauses with INTO for DELETE statements" do
129
- @ds.output(:out, [:deleted__name, :deleted__value]).delete_sql.must_match(/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\] INTO \[OUT\]/)
130
- @ds.output(:out, {:name => :deleted__name, :value => :deleted__value}).delete_sql.must_match(/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\] INTO \[OUT\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\)/)
129
+ @ds.output(:out, [Sequel[:deleted][:name], Sequel[:deleted][:value]]).delete_sql.must_match(/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\] INTO \[OUT\]/)
130
+ @ds.output(:out, {:name => Sequel[:deleted][:name], :value => Sequel[:deleted][:value]}).delete_sql.must_match(/DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\] INTO \[OUT\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\)/)
131
131
  end
132
132
 
133
133
  it "should format OUTPUT clauses without INTO for INSERT statements" do
134
- @ds.output(nil, [:inserted__name, :inserted__value]).insert_sql(:name => "name", :value => 1).must_match(/INSERT INTO \[ITEMS\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) OUTPUT \[INSERTED\].\[(NAME|VALUE)\], \[INSERTED\].\[(NAME|VALUE)\] VALUES \((N'name'|1), (N'name'|1)\)/)
134
+ @ds.output(nil, [Sequel[:inserted][:name], Sequel[:inserted][:value]]).insert_sql(:name => "name", :value => 1).must_match(/INSERT INTO \[ITEMS\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) OUTPUT \[INSERTED\].\[(NAME|VALUE)\], \[INSERTED\].\[(NAME|VALUE)\] VALUES \((N'name'|1), (N'name'|1)\)/)
135
135
  @ds.output(nil, [Sequel::SQL::ColumnAll.new(:inserted)]).insert_sql(:name => "name", :value => 1).must_match(/INSERT INTO \[ITEMS\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) OUTPUT \[INSERTED\].* VALUES \((N'name'|1), (N'name'|1)\)/)
136
136
  end
137
137
 
138
138
  it "should format OUTPUT clauses with INTO for INSERT statements" do
139
- @ds.output(:out, [:inserted__name, :inserted__value]).insert_sql(:name => "name", :value => 1).must_match(/INSERT INTO \[ITEMS\] \((\[NAME\]|\[VALUE\]), (\[NAME\]|\[VALUE\])\) OUTPUT \[INSERTED\].\[(NAME|VALUE)\], \[INSERTED\].\[(NAME|VALUE)\] INTO \[OUT\] VALUES \((N'name'|1), (N'name'|1)\)/)
140
- @ds.output(:out, {:name => :inserted__name, :value => :inserted__value}).insert_sql(:name => "name", :value => 1).must_match(/INSERT INTO \[ITEMS\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) OUTPUT \[INSERTED\].\[(NAME|VALUE)\], \[INSERTED\].\[(NAME|VALUE)\] INTO \[OUT\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) VALUES \((N'name'|1), (N'name'|1)\)/)
139
+ @ds.output(:out, [Sequel[:inserted][:name], Sequel[:inserted][:value]]).insert_sql(:name => "name", :value => 1).must_match(/INSERT INTO \[ITEMS\] \((\[NAME\]|\[VALUE\]), (\[NAME\]|\[VALUE\])\) OUTPUT \[INSERTED\].\[(NAME|VALUE)\], \[INSERTED\].\[(NAME|VALUE)\] INTO \[OUT\] VALUES \((N'name'|1), (N'name'|1)\)/)
140
+ @ds.output(:out, {:name => Sequel[:inserted][:name], :value => Sequel[:inserted][:value]}).insert_sql(:name => "name", :value => 1).must_match(/INSERT INTO \[ITEMS\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) OUTPUT \[INSERTED\].\[(NAME|VALUE)\], \[INSERTED\].\[(NAME|VALUE)\] INTO \[OUT\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) VALUES \((N'name'|1), (N'name'|1)\)/)
141
141
  end
142
142
 
143
143
  it "should format OUTPUT clauses without INTO for UPDATE statements" do
144
- @ds.output(nil, [:inserted__name, :deleted__value]).update_sql(:value => 2).must_match(/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\]/)
144
+ @ds.output(nil, [Sequel[:inserted][:name], Sequel[:deleted][:value]]).update_sql(:value => 2).must_match(/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\]/)
145
145
  @ds.output(nil, [Sequel::SQL::ColumnAll.new(:inserted)]).update_sql(:value => 2).must_match(/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[INSERTED\].*/)
146
146
  end
147
147
 
148
148
  it "should format OUTPUT clauses with INTO for UPDATE statements" do
149
- @ds.output(:out, [:inserted__name, :deleted__value]).update_sql(:value => 2).must_match(/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\] INTO \[OUT\]/)
150
- @ds.output(:out, {:name => :inserted__name, :value => :deleted__value}).update_sql(:value => 2).must_match(/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\] INTO \[OUT\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\)/)
149
+ @ds.output(:out, [Sequel[:inserted][:name], Sequel[:deleted][:value]]).update_sql(:value => 2).must_match(/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\] INTO \[OUT\]/)
150
+ @ds.output(:out, {:name => Sequel[:inserted][:name], :value => Sequel[:deleted][:value]}).update_sql(:value => 2).must_match(/UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\] INTO \[OUT\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\)/)
151
151
  end
152
152
 
153
153
  it "should execute OUTPUT clauses in DELETE statements" do
154
154
  @ds.insert(:name => "name", :value => 1)
155
- @ds.output(:out, [:deleted__name, :deleted__value]).delete
155
+ @ds.output(:out, [Sequel[:deleted][:name], Sequel[:deleted][:value]]).delete
156
156
  @db[:out].all.must_equal [{:name => "name", :value => 1}]
157
157
  @ds.insert(:name => "name", :value => 2)
158
- @ds.output(:out, {:name => :deleted__name, :value => :deleted__value}).delete
158
+ @ds.output(:out, {:name => Sequel[:deleted][:name], :value => Sequel[:deleted][:value]}).delete
159
159
  @db[:out].all.must_equal [{:name => "name", :value => 1}, {:name => "name", :value => 2}]
160
160
  end
161
161
 
162
162
  it "should execute OUTPUT clauses in INSERT statements" do
163
- @ds.output(:out, [:inserted__name, :inserted__value]).insert(:name => "name", :value => 1)
163
+ @ds.output(:out, [Sequel[:inserted][:name], Sequel[:inserted][:value]]).insert(:name => "name", :value => 1)
164
164
  @db[:out].all.must_equal [{:name => "name", :value => 1}]
165
- @ds.output(:out, {:name => :inserted__name, :value => :inserted__value}).insert(:name => "name", :value => 2)
165
+ @ds.output(:out, {:name => Sequel[:inserted][:name], :value => Sequel[:inserted][:value]}).insert(:name => "name", :value => 2)
166
166
  @db[:out].all.must_equal [{:name => "name", :value => 1}, {:name => "name", :value => 2}]
167
167
  end
168
168
 
169
169
  it "should execute OUTPUT clauses in UPDATE statements" do
170
170
  @ds.insert(:name => "name", :value => 1)
171
- @ds.output(:out, [:inserted__name, :deleted__value]).update(:value => 2)
171
+ @ds.output(:out, [Sequel[:inserted][:name], Sequel[:deleted][:value]]).update(:value => 2)
172
172
  @db[:out].all.must_equal [{:name => "name", :value => 1}]
173
- @ds.output(:out, {:name => :inserted__name, :value => :deleted__value}).update(:value => 3)
173
+ @ds.output(:out, {:name => Sequel[:inserted][:name], :value => Sequel[:deleted][:value]}).update(:value => 3)
174
174
  @db[:out].all.must_equal [{:name => "name", :value => 1}, {:name => "name", :value => 2}]
175
175
  end
176
176
  end
@@ -216,7 +216,7 @@ describe "MSSQL::Dataset#import" do
216
216
 
217
217
  it "#import should work correctly with an arbitrary output value" do
218
218
  @db.create_table!(:test){primary_key :x; Integer :y}
219
- @ds.output(nil, [:inserted__y, :inserted__x]).import([:y], [[3], [4]]).must_equal [{:y=>3, :x=>1}, {:y=>4, :x=>2}]
219
+ @ds.output(nil, [Sequel[:inserted][:y], Sequel[:inserted][:x]]).import([:y], [[3], [4]]).must_equal [{:y=>3, :x=>1}, {:y=>4, :x=>2}]
220
220
  @ds.all.must_equal [{:x=>1, :y=>3}, {:x=>2, :y=>4}]
221
221
  end
222
222
 
@@ -233,11 +233,11 @@ describe "MSSQL joined datasets" do
233
233
  end
234
234
 
235
235
  it "should format DELETE statements" do
236
- @db[:t1].inner_join(:t2, :t1__pk => :t2__pk).delete_sql.must_equal "DELETE FROM [T1] FROM [T1] INNER JOIN [T2] ON ([T1].[PK] = [T2].[PK])"
236
+ @db[:t1].inner_join(:t2, Sequel[:t1][:pk] => Sequel[:t2][:pk]).delete_sql.must_equal "DELETE FROM [T1] FROM [T1] INNER JOIN [T2] ON ([T1].[PK] = [T2].[PK])"
237
237
  end
238
238
 
239
239
  it "should format UPDATE statements" do
240
- @db[:t1].inner_join(:t2, :t1__pk => :t2__pk).update_sql(:pk => :t2__pk).must_equal "UPDATE [T1] SET [PK] = [T2].[PK] FROM [T1] INNER JOIN [T2] ON ([T1].[PK] = [T2].[PK])"
240
+ @db[:t1].inner_join(:t2, Sequel[:t1][:pk] => Sequel[:t2][:pk]).update_sql(:pk => Sequel[:t2][:pk]).must_equal "UPDATE [T1] SET [PK] = [T2].[PK] FROM [T1] INNER JOIN [T2] ON ([T1].[PK] = [T2].[PK])"
241
241
  end
242
242
  end
243
243
 
@@ -281,7 +281,7 @@ describe "Common Table Expressions" do
281
281
  @ds.insert(:id=>1)
282
282
  @ds2.insert(:id=>2, :parent_id=>1)
283
283
  @ds2.insert(:id=>3, :parent_id=>2)
284
- @ds.with(:t, @ds2).filter(:id => @db[:t].select(:id)).update(:parent_id => @db[:t].filter(:id => :i1__id).select(:parent_id).limit(1))
284
+ @ds.with(:t, @ds2).filter(:id => @db[:t].select(:id)).update(:parent_id => @db[:t].filter(:id => Sequel[:i1][:id]).select(:parent_id).limit(1))
285
285
  @ds[:id => 1].must_equal(:id => 1, :parent_id => nil)
286
286
  @ds[:id => 2].must_equal(:id => 2, :parent_id => 1)
287
287
  @ds[:id => 3].must_equal(:id => 3, :parent_id => 2)
@@ -289,7 +289,7 @@ describe "Common Table Expressions" do
289
289
  end
290
290
 
291
291
  it "using #with_recursive should be able to update" do
292
- ds = @ds.with_recursive(:t, @ds.filter(:parent_id=>1).or(:id => 1), @ds.join(:t, :i=>:parent_id).select(:i1__id, :i1__parent_id), :args=>[:i, :pi])
292
+ ds = @ds.with_recursive(:t, @ds.filter(:parent_id=>1).or(:id => 1), @ds.join(:t, :i=>:parent_id).select(Sequel[:i1][:id], Sequel[:i1][:parent_id]), :args=>[:i, :pi])
293
293
  ds.exclude(:id => @db[:t].select(:i)).update(:parent_id => 1)
294
294
  @ds[:id => 1].must_equal(:id => 1, :parent_id => nil)
295
295
  @ds[:id => 2].must_equal(:id => 2, :parent_id => 1)
@@ -303,7 +303,7 @@ describe "Common Table Expressions" do
303
303
  end
304
304
 
305
305
  it "using #with_recursive should be able to insert" do
306
- ds = @ds2.with_recursive(:t, @ds.filter(:parent_id=>1), @ds.join(:t, :i=>:parent_id).select(:i1__id, :i1__parent_id), :args=>[:i, :pi])
306
+ ds = @ds2.with_recursive(:t, @ds.filter(:parent_id=>1), @ds.join(:t, :i=>:parent_id).select(Sequel[:i1][:id], Sequel[:i1][:parent_id]), :args=>[:i, :pi])
307
307
  ds.insert @db[:t]
308
308
  @ds2.all.must_equal [{:id => 3, :parent_id => 1}, {:id => 4, :parent_id => 1}, {:id => 5, :parent_id => 3}, {:id => 6, :parent_id => 5}]
309
309
  end
@@ -318,8 +318,8 @@ describe "Common Table Expressions" do
318
318
 
319
319
  it "using #with_recursive should be able to delete" do
320
320
  @ds.insert(:id=>7, :parent_id=>2)
321
- ds = @ds.with_recursive(:t, @ds.filter(:parent_id=>1), @ds.join(:t, :i=>:parent_id).select(:i1__id, :i1__parent_id), :args=>[:i, :pi])
322
- ds.filter(:i1__id => @db[:t].select(:i)).delete
321
+ ds = @ds.with_recursive(:t, @ds.filter(:parent_id=>1), @ds.join(:t, :i=>:parent_id).select(Sequel[:i1][:id], Sequel[:i1][:parent_id]), :args=>[:i, :pi])
322
+ ds.filter(Sequel[:i1][:id] => @db[:t].select(:i)).delete
323
323
  @ds.all.must_equal [{:id => 1, :parent_id => nil}, {:id => 2, :parent_id => nil}, {:id => 7, :parent_id => 2}]
324
324
  end
325
325
 
@@ -330,7 +330,7 @@ describe "Common Table Expressions" do
330
330
  end
331
331
 
332
332
  it "using #with_recursive should be able to import" do
333
- ds = @ds2.with_recursive(:t, @ds.filter(:parent_id=>1), @ds.join(:t, :i=>:parent_id).select(:i1__id, :i1__parent_id), :args=>[:i, :pi])
333
+ ds = @ds2.with_recursive(:t, @ds.filter(:parent_id=>1), @ds.join(:t, :i=>:parent_id).select(Sequel[:i1][:id], Sequel[:i1][:parent_id]), :args=>[:i, :pi])
334
334
  ds.import [:id, :parent_id], @db[:t].select(:i, :pi)
335
335
  @ds2.all.must_equal [{:id => 3, :parent_id => 1}, {:id => 4, :parent_id => 1}, {:id => 5, :parent_id => 3}, {:id => 6, :parent_id => 5}]
336
336
  end
@@ -442,11 +442,11 @@ describe "MSSQL::Database#rename_table" do
442
442
  IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'MY')
443
443
  EXECUTE sp_executesql N'create schema MY'
444
444
  SQL
445
- DB.create_table! :MY__foo do
445
+ DB.create_table! Sequel[:MY][:foo] do
446
446
  text :name
447
447
  end
448
- DB.rename_table :MY__foo, :MY__bar
449
- DB.rename_table :MY__bar, :foo
448
+ DB.rename_table Sequel[:MY][:foo], Sequel[:MY][:bar]
449
+ DB.rename_table Sequel[:MY][:bar], :foo
450
450
  end
451
451
  end
452
452
 
@@ -550,14 +550,14 @@ describe "MSSQL::Database#drop_column with a schema" do
550
550
  DB.run "create schema test" rescue nil
551
551
  end
552
552
  after do
553
- DB.drop_table(:test__items)
553
+ DB.drop_table(Sequel[:test][:items])
554
554
  DB.run "drop schema test" rescue nil
555
555
  end
556
556
 
557
557
  it "drops columns with a default value" do
558
- DB.create_table!(:test__items){ Integer :id; String :name, :default => 'widget' }
559
- DB.drop_column(:test__items, :name)
560
- DB[:test__items].columns.must_equal [:id]
558
+ DB.create_table!(Sequel[:test][:items]){ Integer :id; String :name, :default => 'widget' }
559
+ DB.drop_column(Sequel[:test][:items], :name)
560
+ DB[Sequel[:test][:items]].columns.must_equal [:id]
561
561
  end
562
562
  end
563
563
 
@@ -606,24 +606,24 @@ describe "Database#foreign_key_list" do
606
606
  describe "with multiple schemas" do
607
607
  before(:all) do
608
608
  DB.execute_ddl "create schema vendor"
609
- DB.create_table! :vendor__vendors do
609
+ DB.create_table! Sequel[:vendor][:vendors] do
610
610
  primary_key :id
611
611
  varchar :name
612
612
  end
613
- DB.create_table! :vendor__mapping do
613
+ DB.create_table! Sequel[:vendor][:mapping] do
614
614
  integer :vendor_id
615
615
  integer :item_id
616
- foreign_key [:vendor_id], :vendor__vendors, :name => :fk_mapping_vendor
616
+ foreign_key [:vendor_id], Sequel[:vendor][:vendors], :name => :fk_mapping_vendor
617
617
  foreign_key [:item_id], :items, :name => :fk_mapping_item
618
618
  end
619
619
  end
620
620
  after(:all) do
621
- DB.drop_table? :vendor__mapping
622
- DB.drop_table? :vendor__vendors
621
+ DB.drop_table? Sequel[:vendor][:mapping]
622
+ DB.drop_table? Sequel[:vendor][:vendors]
623
623
  DB.execute_ddl "drop schema vendor"
624
624
  end
625
625
  it "should support mixed schema bound tables" do
626
- DB.foreign_key_list(:vendor__mapping).sort_by{|h| h[:name].to_s}.must_equal [{:name => :fk_mapping_item, :table => :items, :columns => [:item_id], :key => [:id], :on_update => :no_action, :on_delete => :no_action }, {:name => :fk_mapping_vendor, :table => Sequel.qualify(:vendor, :vendors), :columns => [:vendor_id], :key => [:id], :on_update => :no_action, :on_delete => :no_action }]
626
+ DB.foreign_key_list(Sequel[:vendor][:mapping]).sort_by{|h| h[:name].to_s}.must_equal [{:name => :fk_mapping_item, :table => :items, :columns => [:item_id], :key => [:id], :on_update => :no_action, :on_delete => :no_action }, {:name => :fk_mapping_vendor, :table => Sequel.qualify(:vendor, :vendors), :columns => [:vendor_id], :key => [:id], :on_update => :no_action, :on_delete => :no_action }]
627
627
  end
628
628
  end
629
629
  end