sequel 4.39.0 → 4.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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