sequel 3.28.0 → 3.29.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 (148) hide show
  1. data/CHANGELOG +119 -3
  2. data/Rakefile +5 -3
  3. data/bin/sequel +1 -5
  4. data/doc/model_hooks.rdoc +9 -1
  5. data/doc/opening_databases.rdoc +49 -40
  6. data/doc/prepared_statements.rdoc +27 -6
  7. data/doc/release_notes/3.28.0.txt +2 -2
  8. data/doc/release_notes/3.29.0.txt +459 -0
  9. data/doc/sharding.rdoc +7 -1
  10. data/doc/testing.rdoc +18 -9
  11. data/doc/transactions.rdoc +41 -1
  12. data/lib/sequel/adapters/ado.rb +28 -17
  13. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  14. data/lib/sequel/adapters/amalgalite.rb +11 -7
  15. data/lib/sequel/adapters/db2.rb +122 -70
  16. data/lib/sequel/adapters/dbi.rb +15 -15
  17. data/lib/sequel/adapters/do.rb +5 -36
  18. data/lib/sequel/adapters/do/mysql.rb +0 -5
  19. data/lib/sequel/adapters/do/postgres.rb +0 -5
  20. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  21. data/lib/sequel/adapters/firebird.rb +3 -6
  22. data/lib/sequel/adapters/ibmdb.rb +24 -16
  23. data/lib/sequel/adapters/informix.rb +2 -4
  24. data/lib/sequel/adapters/jdbc.rb +47 -11
  25. data/lib/sequel/adapters/jdbc/as400.rb +5 -24
  26. data/lib/sequel/adapters/jdbc/db2.rb +0 -5
  27. data/lib/sequel/adapters/jdbc/derby.rb +217 -0
  28. data/lib/sequel/adapters/jdbc/firebird.rb +0 -5
  29. data/lib/sequel/adapters/jdbc/h2.rb +10 -12
  30. data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
  31. data/lib/sequel/adapters/jdbc/informix.rb +0 -5
  32. data/lib/sequel/adapters/jdbc/jtds.rb +0 -5
  33. data/lib/sequel/adapters/jdbc/mysql.rb +0 -10
  34. data/lib/sequel/adapters/jdbc/oracle.rb +70 -3
  35. data/lib/sequel/adapters/jdbc/postgresql.rb +0 -11
  36. data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
  37. data/lib/sequel/adapters/jdbc/sqlserver.rb +0 -5
  38. data/lib/sequel/adapters/jdbc/transactions.rb +56 -7
  39. data/lib/sequel/adapters/mock.rb +315 -0
  40. data/lib/sequel/adapters/mysql.rb +64 -51
  41. data/lib/sequel/adapters/mysql2.rb +15 -9
  42. data/lib/sequel/adapters/odbc.rb +13 -6
  43. data/lib/sequel/adapters/odbc/db2.rb +0 -4
  44. data/lib/sequel/adapters/odbc/mssql.rb +0 -5
  45. data/lib/sequel/adapters/openbase.rb +2 -4
  46. data/lib/sequel/adapters/oracle.rb +333 -51
  47. data/lib/sequel/adapters/postgres.rb +80 -27
  48. data/lib/sequel/adapters/shared/access.rb +0 -6
  49. data/lib/sequel/adapters/shared/db2.rb +13 -15
  50. data/lib/sequel/adapters/shared/firebird.rb +6 -6
  51. data/lib/sequel/adapters/shared/mssql.rb +23 -18
  52. data/lib/sequel/adapters/shared/mysql.rb +6 -6
  53. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
  54. data/lib/sequel/adapters/shared/oracle.rb +185 -30
  55. data/lib/sequel/adapters/shared/postgres.rb +35 -18
  56. data/lib/sequel/adapters/shared/progress.rb +0 -6
  57. data/lib/sequel/adapters/shared/sqlite.rb +116 -37
  58. data/lib/sequel/adapters/sqlite.rb +16 -8
  59. data/lib/sequel/adapters/swift.rb +5 -5
  60. data/lib/sequel/adapters/swift/mysql.rb +0 -5
  61. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  62. data/lib/sequel/adapters/swift/sqlite.rb +6 -4
  63. data/lib/sequel/adapters/tinytds.rb +13 -10
  64. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -0
  65. data/lib/sequel/core.rb +40 -0
  66. data/lib/sequel/database/connecting.rb +1 -2
  67. data/lib/sequel/database/dataset.rb +3 -3
  68. data/lib/sequel/database/dataset_defaults.rb +58 -0
  69. data/lib/sequel/database/misc.rb +62 -2
  70. data/lib/sequel/database/query.rb +113 -49
  71. data/lib/sequel/database/schema_methods.rb +7 -2
  72. data/lib/sequel/dataset/actions.rb +37 -19
  73. data/lib/sequel/dataset/features.rb +24 -0
  74. data/lib/sequel/dataset/graph.rb +7 -6
  75. data/lib/sequel/dataset/misc.rb +11 -3
  76. data/lib/sequel/dataset/mutation.rb +2 -3
  77. data/lib/sequel/dataset/prepared_statements.rb +6 -4
  78. data/lib/sequel/dataset/query.rb +46 -15
  79. data/lib/sequel/dataset/sql.rb +28 -4
  80. data/lib/sequel/extensions/named_timezones.rb +5 -0
  81. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  82. data/lib/sequel/model.rb +2 -1
  83. data/lib/sequel/model/associations.rb +115 -33
  84. data/lib/sequel/model/base.rb +91 -31
  85. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  86. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  87. data/lib/sequel/plugins/force_encoding.rb +6 -6
  88. data/lib/sequel/plugins/identity_map.rb +1 -1
  89. data/lib/sequel/plugins/many_through_many.rb +6 -10
  90. data/lib/sequel/plugins/prepared_statements.rb +12 -1
  91. data/lib/sequel/plugins/prepared_statements_associations.rb +1 -1
  92. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  93. data/lib/sequel/plugins/serialization.rb +6 -1
  94. data/lib/sequel/plugins/sharding.rb +0 -5
  95. data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
  96. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  97. data/lib/sequel/plugins/update_primary_key.rb +1 -1
  98. data/lib/sequel/timezones.rb +42 -42
  99. data/lib/sequel/version.rb +1 -1
  100. data/spec/adapters/mssql_spec.rb +29 -29
  101. data/spec/adapters/mysql_spec.rb +86 -104
  102. data/spec/adapters/oracle_spec.rb +48 -76
  103. data/spec/adapters/postgres_spec.rb +98 -33
  104. data/spec/adapters/spec_helper.rb +0 -5
  105. data/spec/adapters/sqlite_spec.rb +24 -21
  106. data/spec/core/connection_pool_spec.rb +9 -15
  107. data/spec/core/core_sql_spec.rb +20 -31
  108. data/spec/core/database_spec.rb +491 -227
  109. data/spec/core/dataset_spec.rb +638 -1051
  110. data/spec/core/expression_filters_spec.rb +0 -1
  111. data/spec/core/mock_adapter_spec.rb +378 -0
  112. data/spec/core/object_graph_spec.rb +48 -114
  113. data/spec/core/schema_generator_spec.rb +3 -3
  114. data/spec/core/schema_spec.rb +51 -114
  115. data/spec/core/spec_helper.rb +3 -90
  116. data/spec/extensions/class_table_inheritance_spec.rb +1 -1
  117. data/spec/extensions/dataset_associations_spec.rb +199 -0
  118. data/spec/extensions/instance_hooks_spec.rb +71 -0
  119. data/spec/extensions/named_timezones_spec.rb +22 -2
  120. data/spec/extensions/nested_attributes_spec.rb +3 -0
  121. data/spec/extensions/schema_spec.rb +1 -1
  122. data/spec/extensions/serialization_modification_detection_spec.rb +1 -0
  123. data/spec/extensions/serialization_spec.rb +5 -8
  124. data/spec/extensions/spec_helper.rb +4 -0
  125. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  126. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  127. data/spec/integration/associations_test.rb +123 -12
  128. data/spec/integration/dataset_test.rb +140 -47
  129. data/spec/integration/eager_loader_test.rb +19 -21
  130. data/spec/integration/model_test.rb +80 -1
  131. data/spec/integration/plugin_test.rb +179 -128
  132. data/spec/integration/prepared_statement_test.rb +92 -91
  133. data/spec/integration/schema_test.rb +42 -23
  134. data/spec/integration/spec_helper.rb +25 -31
  135. data/spec/integration/timezone_test.rb +38 -12
  136. data/spec/integration/transaction_test.rb +161 -34
  137. data/spec/integration/type_test.rb +3 -3
  138. data/spec/model/association_reflection_spec.rb +83 -7
  139. data/spec/model/associations_spec.rb +393 -676
  140. data/spec/model/base_spec.rb +186 -116
  141. data/spec/model/dataset_methods_spec.rb +7 -27
  142. data/spec/model/eager_loading_spec.rb +343 -867
  143. data/spec/model/hooks_spec.rb +160 -79
  144. data/spec/model/model_spec.rb +118 -165
  145. data/spec/model/plugins_spec.rb +7 -13
  146. data/spec/model/record_spec.rb +138 -207
  147. data/spec/model/spec_helper.rb +10 -73
  148. metadata +14 -8
@@ -39,6 +39,48 @@ module Sequel
39
39
  convert_output_timestamp(v, Sequel.database_timezone)
40
40
  end
41
41
 
42
+ # Converts the object to the given +output_timezone+.
43
+ def convert_output_timestamp(v, output_timezone)
44
+ if output_timezone
45
+ if v.is_a?(DateTime)
46
+ case output_timezone
47
+ when :utc
48
+ v.new_offset(0)
49
+ when :local
50
+ v.new_offset(local_offset_for_datetime(v))
51
+ else
52
+ convert_output_datetime_other(v, output_timezone)
53
+ end
54
+ else
55
+ v.send(output_timezone == :utc ? :getutc : :getlocal)
56
+ end
57
+ else
58
+ v
59
+ end
60
+ end
61
+
62
+ # Converts the given object from the given input timezone to the
63
+ # +application_timezone+ using +convert_input_timestamp+ and
64
+ # +convert_output_timestamp+.
65
+ def convert_timestamp(v, input_timezone)
66
+ begin
67
+ if v.is_a?(Date) && !v.is_a?(DateTime)
68
+ # Dates handled specially as they are assumed to already be in the application_timezone
69
+ if datetime_class == DateTime
70
+ DateTime.civil(v.year, v.month, v.day, 0, 0, 0, application_timezone == :local ? (defined?(Rational) ? Rational(Time.local(v.year, v.month, v.day).utc_offset, 86400) : Time.local(v.year, v.month, v.day).utc_offset/86400.0) : 0)
71
+ else
72
+ Time.send(application_timezone == :utc ? :utc : :local, v.year, v.month, v.day)
73
+ end
74
+ else
75
+ convert_output_timestamp(convert_input_timestamp(v, input_timezone), application_timezone)
76
+ end
77
+ rescue InvalidValue
78
+ raise
79
+ rescue => e
80
+ raise convert_exception_class(e, InvalidValue)
81
+ end
82
+ end
83
+
42
84
  # Convert the given object into an object of <tt>Sequel.datetime_class</tt> in the
43
85
  # +application_timezone+. Used when coverting datetime/timestamp columns
44
86
  # returned by the database.
@@ -135,48 +177,6 @@ module Sequel
135
177
  raise InvalidValue, "Invalid output_timezone: #{output_timezone.inspect}"
136
178
  end
137
179
 
138
- # Converts the object to the given +output_timezone+.
139
- def convert_output_timestamp(v, output_timezone)
140
- if output_timezone
141
- if v.is_a?(DateTime)
142
- case output_timezone
143
- when :utc
144
- v.new_offset(0)
145
- when :local
146
- v.new_offset(local_offset_for_datetime(v))
147
- else
148
- convert_output_datetime_other(v, output_timezone)
149
- end
150
- else
151
- v.send(output_timezone == :utc ? :getutc : :getlocal)
152
- end
153
- else
154
- v
155
- end
156
- end
157
-
158
- # Converts the given object from the given input timezone to the
159
- # +application_timezone+ using +convert_input_timestamp+ and
160
- # +convert_output_timestamp+.
161
- def convert_timestamp(v, input_timezone)
162
- begin
163
- if v.is_a?(Date) && !v.is_a?(DateTime)
164
- # Dates handled specially as they are assumed to already be in the application_timezone
165
- if datetime_class == DateTime
166
- DateTime.civil(v.year, v.month, v.day, 0, 0, 0, application_timezone == :local ? (defined?(Rational) ? Rational(Time.local(v.year, v.month, v.day).utc_offset, 86400) : Time.local(v.year, v.month, v.day).utc_offset/86400.0) : 0)
167
- else
168
- Time.send(application_timezone == :utc ? :utc : :local, v.year, v.month, v.day)
169
- end
170
- else
171
- convert_output_timestamp(convert_input_timestamp(v, input_timezone), application_timezone)
172
- end
173
- rescue InvalidValue
174
- raise
175
- rescue => e
176
- raise convert_exception_class(e, InvalidValue)
177
- end
178
- end
179
-
180
180
  # Convert the timezone setter argument. Returns argument given by default,
181
181
  # exists for easier overriding in extensions.
182
182
  def convert_timezone_setter_arg(tz)
@@ -3,7 +3,7 @@ module Sequel
3
3
  MAJOR = 3
4
4
  # The minor version of Sequel. Bumped for every non-patch level
5
5
  # release, generally around once a month.
6
- MINOR = 28
6
+ MINOR = 29
7
7
  # The tiny version of Sequel. Usually 0, only bumped for bugfix
8
8
  # releases that fix regressions from previous versions.
9
9
  TINY = 0
@@ -63,12 +63,12 @@ end
63
63
  describe "MSSQL Dataset#join_table" do
64
64
  specify "should emulate the USING clause with ON" do
65
65
  MSSQL_DB[:items].join(:categories, [:id]).sql.should ==
66
- 'SELECT * FROM ITEMS INNER JOIN CATEGORIES ON (CATEGORIES.ID = ITEMS.ID)'
67
- ['SELECT * FROM ITEMS INNER JOIN CATEGORIES ON ((CATEGORIES.ID1 = ITEMS.ID1) AND (CATEGORIES.ID2 = ITEMS.ID2))',
68
- 'SELECT * FROM ITEMS INNER JOIN CATEGORIES ON ((CATEGORIES.ID2 = ITEMS.ID2) AND (CATEGORIES.ID1 = ITEMS.ID1))'].
66
+ 'SELECT * FROM [ITEMS] INNER JOIN [CATEGORIES] ON ([CATEGORIES].[ID] = [ITEMS].[ID])'
67
+ ['SELECT * FROM [ITEMS] INNER JOIN [CATEGORIES] ON (([CATEGORIES].[ID1] = [ITEMS].[ID1]) AND ([CATEGORIES].[ID2] = [ITEMS].[ID2]))',
68
+ 'SELECT * FROM [ITEMS] INNER JOIN [CATEGORIES] ON (([CATEGORIES].[ID2] = [ITEMS].[ID2]) AND ([CATEGORIES].[ID1] = [ITEMS].[ID1]))'].
69
69
  should include(MSSQL_DB[:items].join(:categories, [:id1, :id2]).sql)
70
70
  MSSQL_DB[:items___i].join(:categories___c, [:id]).sql.should ==
71
- 'SELECT * FROM ITEMS AS I INNER JOIN CATEGORIES AS C ON (C.ID = I.ID)'
71
+ 'SELECT * FROM [ITEMS] AS [I] INNER JOIN [CATEGORIES] AS [C] ON ([C].[ID] = [I].[ID])'
72
72
  end
73
73
  end
74
74
 
@@ -86,44 +86,44 @@ describe "MSSQL Dataset#output" do
86
86
 
87
87
  specify "should format OUTPUT clauses without INTO for DELETE statements" do
88
88
  @ds.output(nil, [:deleted__name, :deleted__value]).delete_sql.should =~
89
- /DELETE FROM ITEMS OUTPUT DELETED.(NAME|VALUE), DELETED.(NAME|VALUE)/
89
+ /DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\]/
90
90
  @ds.output(nil, [:deleted.*]).delete_sql.should =~
91
- /DELETE FROM ITEMS OUTPUT DELETED.*/
91
+ /DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].*/
92
92
  end
93
93
 
94
94
  specify "should format OUTPUT clauses with INTO for DELETE statements" do
95
95
  @ds.output(:out, [:deleted__name, :deleted__value]).delete_sql.should =~
96
- /DELETE FROM ITEMS OUTPUT DELETED.(NAME|VALUE), DELETED.(NAME|VALUE) INTO OUT/
96
+ /DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\] INTO \[OUT\]/
97
97
  @ds.output(:out, {:name => :deleted__name, :value => :deleted__value}).delete_sql.should =~
98
- /DELETE FROM ITEMS OUTPUT DELETED.(NAME|VALUE), DELETED.(NAME|VALUE) INTO OUT \((NAME|VALUE), (NAME|VALUE)\)/
98
+ /DELETE FROM \[ITEMS\] OUTPUT \[DELETED\].\[(NAME|VALUE)\], \[DELETED\].\[(NAME|VALUE)\] INTO \[OUT\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\)/
99
99
  end
100
100
 
101
101
  specify "should format OUTPUT clauses without INTO for INSERT statements" do
102
102
  @ds.output(nil, [:inserted__name, :inserted__value]).insert_sql(:name => "name", :value => 1).should =~
103
- /INSERT INTO ITEMS \((NAME|VALUE), (NAME|VALUE)\) OUTPUT INSERTED.(NAME|VALUE), INSERTED.(NAME|VALUE) VALUES \((N'name'|1), (N'name'|1)\)/
103
+ /INSERT INTO \[ITEMS\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) OUTPUT \[INSERTED\].\[(NAME|VALUE)\], \[INSERTED\].\[(NAME|VALUE)\] VALUES \((N'name'|1), (N'name'|1)\)/
104
104
  @ds.output(nil, [:inserted.*]).insert_sql(:name => "name", :value => 1).should =~
105
- /INSERT INTO ITEMS \((NAME|VALUE), (NAME|VALUE)\) OUTPUT INSERTED.* VALUES \((N'name'|1), (N'name'|1)\)/
105
+ /INSERT INTO \[ITEMS\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\) OUTPUT \[INSERTED\].* VALUES \((N'name'|1), (N'name'|1)\)/
106
106
  end
107
107
 
108
108
  specify "should format OUTPUT clauses with INTO for INSERT statements" do
109
109
  @ds.output(:out, [:inserted__name, :inserted__value]).insert_sql(:name => "name", :value => 1).should =~
110
- /INSERT INTO ITEMS \((NAME|VALUE), (NAME|VALUE)\) OUTPUT INSERTED.(NAME|VALUE), INSERTED.(NAME|VALUE) INTO OUT VALUES \((N'name'|1), (N'name'|1)\)/
110
+ /INSERT INTO \[ITEMS\] \((\[NAME\]|\[VALUE\]), (\[NAME\]|\[VALUE\])\) OUTPUT \[INSERTED\].\[(NAME|VALUE)\], \[INSERTED\].\[(NAME|VALUE)\] INTO \[OUT\] VALUES \((N'name'|1), (N'name'|1)\)/
111
111
  @ds.output(:out, {:name => :inserted__name, :value => :inserted__value}).insert_sql(:name => "name", :value => 1).should =~
112
- /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)\)/
112
+ /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)\)/
113
113
  end
114
114
 
115
115
  specify "should format OUTPUT clauses without INTO for UPDATE statements" do
116
116
  @ds.output(nil, [:inserted__name, :deleted__value]).update_sql(:value => 2).should =~
117
- /UPDATE ITEMS SET VALUE = 2 OUTPUT (INSERTED.NAME|DELETED.VALUE), (INSERTED.NAME|DELETED.VALUE)/
117
+ /UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\]/
118
118
  @ds.output(nil, [:inserted.*]).update_sql(:value => 2).should =~
119
- /UPDATE ITEMS SET VALUE = 2 OUTPUT INSERTED.*/
119
+ /UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[INSERTED\].*/
120
120
  end
121
121
 
122
122
  specify "should format OUTPUT clauses with INTO for UPDATE statements" do
123
123
  @ds.output(:out, [:inserted__name, :deleted__value]).update_sql(:value => 2).should =~
124
- /UPDATE ITEMS SET VALUE = 2 OUTPUT (INSERTED.NAME|DELETED.VALUE), (INSERTED.NAME|DELETED.VALUE) INTO OUT/
124
+ /UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\] INTO \[OUT\]/
125
125
  @ds.output(:out, {:name => :inserted__name, :value => :deleted__value}).update_sql(:value => 2).should =~
126
- /UPDATE ITEMS SET VALUE = 2 OUTPUT (INSERTED.NAME|DELETED.VALUE), (INSERTED.NAME|DELETED.VALUE) INTO OUT \((NAME|VALUE), (NAME|VALUE)\)/
126
+ /UPDATE \[ITEMS\] SET \[VALUE\] = 2 OUTPUT \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\], \[(INSERTED\].\[NAME|DELETED\].\[VALUE)\] INTO \[OUT\] \(\[(NAME|VALUE)\], \[(NAME|VALUE)\]\)/
127
127
  end
128
128
 
129
129
  specify "should execute OUTPUT clauses in DELETE statements" do
@@ -164,23 +164,23 @@ describe "MSSQL dataset" do
164
164
  end
165
165
 
166
166
  specify "should prepend UPDATE statements with WITH clause" do
167
- @ds1.update_sql(:x => :y).should == 'WITH T AS (SELECT * FROM X) UPDATE T SET X = Y'
168
- @ds2.update_sql(:x => :y).should == 'WITH T AS (SELECT * FROM X UNION ALL SELECT * FROM T) UPDATE T SET X = Y'
167
+ @ds1.update_sql(:x => :y).should == 'WITH [T] AS (SELECT * FROM [X]) UPDATE [T] SET [X] = [Y]'
168
+ @ds2.update_sql(:x => :y).should == 'WITH [T] AS (SELECT * FROM [X] UNION ALL SELECT * FROM [T]) UPDATE [T] SET [X] = [Y]'
169
169
  end
170
170
 
171
171
  specify "should prepend DELETE statements with WITH clause" do
172
- @ds1.filter(:y => 1).delete_sql.should == 'WITH T AS (SELECT * FROM X) DELETE FROM T WHERE (Y = 1)'
173
- @ds2.filter(:y => 1).delete_sql.should == 'WITH T AS (SELECT * FROM X UNION ALL SELECT * FROM T) DELETE FROM T WHERE (Y = 1)'
172
+ @ds1.filter(:y => 1).delete_sql.should == 'WITH [T] AS (SELECT * FROM [X]) DELETE FROM [T] WHERE ([Y] = 1)'
173
+ @ds2.filter(:y => 1).delete_sql.should == 'WITH [T] AS (SELECT * FROM [X] UNION ALL SELECT * FROM [T]) DELETE FROM [T] WHERE ([Y] = 1)'
174
174
  end
175
175
 
176
176
  specify "should prepend INSERT statements with WITH clause" do
177
- @ds1.insert_sql(@db[:t]).should == 'WITH T AS (SELECT * FROM X) INSERT INTO T SELECT * FROM T'
178
- @ds2.insert_sql(@db[:t]).should == 'WITH T AS (SELECT * FROM X UNION ALL SELECT * FROM T) INSERT INTO T SELECT * FROM T'
177
+ @ds1.insert_sql(@db[:t]).should == 'WITH [T] AS (SELECT * FROM [X]) INSERT INTO [T] SELECT * FROM [T]'
178
+ @ds2.insert_sql(@db[:t]).should == 'WITH [T] AS (SELECT * FROM [X] UNION ALL SELECT * FROM [T]) INSERT INTO [T] SELECT * FROM [T]'
179
179
  end
180
180
 
181
181
  specify "should move WITH clause on joined dataset to top level" do
182
- @db[:s].inner_join(@ds1).sql.should == "WITH T AS (SELECT * FROM X) SELECT * FROM S INNER JOIN (SELECT * FROM T) AS T1"
183
- @ds1.inner_join(@db[:s].with(:s, @db[:y])).sql.should == "WITH T AS (SELECT * FROM X), S AS (SELECT * FROM Y) SELECT * FROM T INNER JOIN (SELECT * FROM S) AS T1"
182
+ @db[:s].inner_join(@ds1).sql.should == "WITH [T] AS (SELECT * FROM [X]) SELECT * FROM [S] INNER JOIN (SELECT * FROM [T]) AS [T1]"
183
+ @ds1.inner_join(@db[:s].with(:s, @db[:y])).sql.should == "WITH [T] AS (SELECT * FROM [X]), [S] AS (SELECT * FROM [Y]) SELECT * FROM [T] INNER JOIN (SELECT * FROM [S]) AS [T1]"
184
184
  end
185
185
 
186
186
  describe "on #import" do
@@ -208,10 +208,10 @@ describe "MSSQL dataset" do
208
208
  @db[:items].with(:items, @db[:inventory].group(:type)).import([:x, :y], [[1, 2], [3, 4], [5, 6]], :slice => 2)
209
209
  @db.import_sqls.should == [
210
210
  'BEGIN',
211
- "WITH ITEMS AS (SELECT * FROM INVENTORY GROUP BY TYPE) INSERT INTO ITEMS (X, Y) SELECT 1, 2 UNION ALL SELECT 3, 4",
211
+ "WITH [ITEMS] AS (SELECT * FROM [INVENTORY] GROUP BY [TYPE]) INSERT INTO [ITEMS] ([X], [Y]) SELECT 1, 2 UNION ALL SELECT 3, 4",
212
212
  'COMMIT',
213
213
  'BEGIN',
214
- "WITH ITEMS AS (SELECT * FROM INVENTORY GROUP BY TYPE) INSERT INTO ITEMS (X, Y) SELECT 5, 6",
214
+ "WITH [ITEMS] AS (SELECT * FROM [INVENTORY] GROUP BY [TYPE]) INSERT INTO [ITEMS] ([X], [Y]) SELECT 5, 6",
215
215
  'COMMIT'
216
216
  ]
217
217
  end
@@ -226,12 +226,12 @@ describe "MSSQL joined datasets" do
226
226
 
227
227
  specify "should format DELETE statements" do
228
228
  @db[:t1].inner_join(:t2, :t1__pk => :t2__pk).delete_sql.should ==
229
- "DELETE FROM T1 FROM T1 INNER JOIN T2 ON (T1.PK = T2.PK)"
229
+ "DELETE FROM [T1] FROM [T1] INNER JOIN [T2] ON ([T1].[PK] = [T2].[PK])"
230
230
  end
231
231
 
232
232
  specify "should format UPDATE statements" do
233
233
  @db[:t1].inner_join(:t2, :t1__pk => :t2__pk).update_sql(:pk => :t2__pk).should ==
234
- "UPDATE T1 SET PK = T2.PK FROM T1 INNER JOIN T2 ON (T1.PK = T2.PK)"
234
+ "UPDATE [T1] SET [PK] = [T2].[PK] FROM [T1] INNER JOIN [T2] ON ([T1].[PK] = [T2].[PK])"
235
235
  end
236
236
  end
237
237
 
@@ -370,7 +370,7 @@ describe "MSSSQL::Dataset#into" do
370
370
  end
371
371
 
372
372
  specify "should format SELECT statement" do
373
- @db[:t].into(:new).select_sql.should == "SELECT * INTO NEW FROM T"
373
+ @db[:t].into(:new).select_sql.should == "SELECT * INTO [NEW] FROM [T]"
374
374
  end
375
375
 
376
376
  specify "should select rows into a new table" do
@@ -45,22 +45,22 @@ describe "MySQL", '#create_table' do
45
45
 
46
46
  specify "should allow to specify options for MySQL" do
47
47
  @db.create_table(:dolls, :engine => 'MyISAM', :charset => 'latin2'){text :name}
48
- @db.sqls.should == ["CREATE TABLE dolls (name text) ENGINE=MyISAM DEFAULT CHARSET=latin2"]
48
+ @db.sqls.should == ["CREATE TABLE `dolls` (`name` text) ENGINE=MyISAM DEFAULT CHARSET=latin2"]
49
49
  end
50
50
 
51
51
  specify "should create a temporary table" do
52
52
  @db.create_table(:tmp_dolls, :temp => true, :engine => 'MyISAM', :charset => 'latin2'){text :name}
53
- @db.sqls.should == ["CREATE TEMPORARY TABLE tmp_dolls (name text) ENGINE=MyISAM DEFAULT CHARSET=latin2"]
53
+ @db.sqls.should == ["CREATE TEMPORARY TABLE `tmp_dolls` (`name` text) ENGINE=MyISAM DEFAULT CHARSET=latin2"]
54
54
  end
55
55
 
56
56
  specify "should not use a default for a String :text=>true type" do
57
57
  @db.create_table(:dolls){String :name, :text=>true, :default=>'blah'}
58
- @db.sqls.should == ["CREATE TABLE dolls (name text)"]
58
+ @db.sqls.should == ["CREATE TABLE `dolls` (`name` text)"]
59
59
  end
60
60
 
61
61
  specify "should not use a default for a File type" do
62
62
  @db.create_table(:dolls){File :name, :default=>'blah'}
63
- @db.sqls.should == ["CREATE TABLE dolls (name blob)"]
63
+ @db.sqls.should == ["CREATE TABLE `dolls` (`name` blob)"]
64
64
  end
65
65
 
66
66
  specify "should respect the size option for File type" do
@@ -112,18 +112,18 @@ if MYSQL_DB.adapter_scheme == :mysql
112
112
  @ds = @db[:booltest]
113
113
  end
114
114
  after do
115
- Sequel::MySQL.convert_tinyint_to_bool = true
115
+ @db.convert_tinyint_to_bool = true
116
116
  @db.drop_table(:booltest)
117
117
  end
118
118
 
119
119
  specify "should consider tinyint(1) datatypes as boolean if set, but not larger tinyints" do
120
120
  @db.schema(:booltest, :reload=>true).should == [[:b, {:type=>:boolean, :allow_null=>true, :primary_key=>false, :default=>nil, :ruby_default=>nil, :db_type=>"tinyint(1)"}, ], [:i, {:type=>:integer, :allow_null=>true, :primary_key=>false, :default=>nil, :ruby_default=>nil, :db_type=>"tinyint(4)"}, ]]
121
- Sequel::MySQL.convert_tinyint_to_bool = false
121
+ @db.convert_tinyint_to_bool = false
122
122
  @db.schema(:booltest, :reload=>true).should == [[:b, {:type=>:integer, :allow_null=>true, :primary_key=>false, :default=>nil, :ruby_default=>nil, :db_type=>"tinyint(1)"}, ], [:i, {:type=>:integer, :allow_null=>true, :primary_key=>false, :default=>nil, :ruby_default=>nil, :db_type=>"tinyint(4)"}, ]]
123
123
  end
124
124
 
125
125
  specify "should return tinyint(1)s as bools and tinyint(4)s as integers when set" do
126
- Sequel::MySQL.convert_tinyint_to_bool = true
126
+ @db.convert_tinyint_to_bool = true
127
127
  @ds.delete
128
128
  @ds << {:b=>true, :i=>10}
129
129
  @ds.all.should == [{:b=>true, :i=>10}]
@@ -136,7 +136,7 @@ if MYSQL_DB.adapter_scheme == :mysql
136
136
  end
137
137
 
138
138
  specify "should return all tinyints as integers when unset" do
139
- Sequel::MySQL.convert_tinyint_to_bool = false
139
+ @db.convert_tinyint_to_bool = false
140
140
  @ds.delete
141
141
  @ds << {:b=>true, :i=>10}
142
142
  @ds.all.should == [{:b=>1, :i=>10}]
@@ -226,12 +226,12 @@ describe "A MySQL dataset" do
226
226
 
227
227
  specify "should support ORDER clause in UPDATE statements" do
228
228
  @d.order(:name).update_sql(:value => 1).should == \
229
- 'UPDATE items SET value = 1 ORDER BY name'
229
+ 'UPDATE `items` SET `value` = 1 ORDER BY `name`'
230
230
  end
231
231
 
232
232
  specify "should support LIMIT clause in UPDATE statements" do
233
233
  @d.limit(10).update_sql(:value => 1).should == \
234
- 'UPDATE items SET value = 1 LIMIT 10'
234
+ 'UPDATE `items` SET `value` = 1 LIMIT 10'
235
235
  end
236
236
 
237
237
  specify "should support regexps" do
@@ -299,43 +299,43 @@ describe "MySQL join expressions" do
299
299
  end
300
300
  specify "should support natural left joins" do
301
301
  @ds.join_table(:natural_left, :nodes).sql.should == \
302
- 'SELECT * FROM nodes NATURAL LEFT JOIN nodes'
302
+ 'SELECT * FROM `nodes` NATURAL LEFT JOIN `nodes`'
303
303
  end
304
304
  specify "should support natural right joins" do
305
305
  @ds.join_table(:natural_right, :nodes).sql.should == \
306
- 'SELECT * FROM nodes NATURAL RIGHT JOIN nodes'
306
+ 'SELECT * FROM `nodes` NATURAL RIGHT JOIN `nodes`'
307
307
  end
308
308
  specify "should support natural left outer joins" do
309
309
  @ds.join_table(:natural_left_outer, :nodes).sql.should == \
310
- 'SELECT * FROM nodes NATURAL LEFT OUTER JOIN nodes'
310
+ 'SELECT * FROM `nodes` NATURAL LEFT OUTER JOIN `nodes`'
311
311
  end
312
312
  specify "should support natural right outer joins" do
313
313
  @ds.join_table(:natural_right_outer, :nodes).sql.should == \
314
- 'SELECT * FROM nodes NATURAL RIGHT OUTER JOIN nodes'
314
+ 'SELECT * FROM `nodes` NATURAL RIGHT OUTER JOIN `nodes`'
315
315
  end
316
316
  specify "should support natural inner joins" do
317
317
  @ds.join_table(:natural_inner, :nodes).sql.should == \
318
- 'SELECT * FROM nodes NATURAL LEFT JOIN nodes'
318
+ 'SELECT * FROM `nodes` NATURAL LEFT JOIN `nodes`'
319
319
  end
320
320
  specify "should support cross joins" do
321
321
  @ds.join_table(:cross, :nodes).sql.should == \
322
- 'SELECT * FROM nodes CROSS JOIN nodes'
322
+ 'SELECT * FROM `nodes` CROSS JOIN `nodes`'
323
323
  end
324
324
  specify "should support cross joins as inner joins if conditions are used" do
325
325
  @ds.join_table(:cross, :nodes, :id=>:id).sql.should == \
326
- 'SELECT * FROM nodes INNER JOIN nodes ON (nodes.id = nodes.id)'
326
+ 'SELECT * FROM `nodes` INNER JOIN `nodes` ON (`nodes`.`id` = `nodes`.`id`)'
327
327
  end
328
328
  specify "should support straight joins (force left table to be read before right)" do
329
329
  @ds.join_table(:straight, :nodes).sql.should == \
330
- 'SELECT * FROM nodes STRAIGHT_JOIN nodes'
330
+ 'SELECT * FROM `nodes` STRAIGHT_JOIN `nodes`'
331
331
  end
332
332
  specify "should support natural joins on multiple tables." do
333
333
  @ds.join_table(:natural_left_outer, [:nodes, :branches]).sql.should == \
334
- 'SELECT * FROM nodes NATURAL LEFT OUTER JOIN (nodes, branches)'
334
+ 'SELECT * FROM `nodes` NATURAL LEFT OUTER JOIN (`nodes`, `branches`)'
335
335
  end
336
336
  specify "should support straight joins on multiple tables." do
337
337
  @ds.join_table(:straight, [:nodes,:branches]).sql.should == \
338
- 'SELECT * FROM nodes STRAIGHT_JOIN (nodes, branches)'
338
+ 'SELECT * FROM `nodes` STRAIGHT_JOIN (`nodes`, `branches`)'
339
339
  end
340
340
  end
341
341
 
@@ -354,12 +354,12 @@ describe "Joined MySQL dataset" do
354
354
  proc {@ds.having('blah')}.should_not raise_error
355
355
 
356
356
  @ds.having('blah').sql.should == \
357
- "SELECT * FROM nodes HAVING (blah)"
357
+ "SELECT * FROM `nodes` HAVING (blah)"
358
358
  end
359
359
 
360
360
  specify "should put a having clause before an order by clause" do
361
361
  @ds.order(:aaa).having(:bbb => :ccc).sql.should == \
362
- "SELECT * FROM nodes HAVING (bbb = ccc) ORDER BY aaa"
362
+ "SELECT * FROM `nodes` HAVING (`bbb` = `ccc`) ORDER BY `aaa`"
363
363
  end
364
364
  end
365
365
 
@@ -453,17 +453,17 @@ describe "A MySQL database with table options" do
453
453
 
454
454
  specify "should allow to pass custom options (engine, charset, collate) for table creation" do
455
455
  @db.create_table(:items, @options){Integer :size; text :name}
456
- @db.sqls.should == ["CREATE TABLE items (size integer, name text) ENGINE=MyISAM DEFAULT CHARSET=latin1 DEFAULT COLLATE=latin1_swedish_ci"]
456
+ @db.sqls.should == ["CREATE TABLE `items` (`size` integer, `name` text) ENGINE=MyISAM DEFAULT CHARSET=latin1 DEFAULT COLLATE=latin1_swedish_ci"]
457
457
  end
458
458
 
459
459
  specify "should use default options if specified (engine, charset, collate) for table creation" do
460
460
  @db.create_table(:items){Integer :size; text :name}
461
- @db.sqls.should == ["CREATE TABLE items (size integer, name text) ENGINE=InnoDB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci"]
461
+ @db.sqls.should == ["CREATE TABLE `items` (`size` integer, `name` text) ENGINE=InnoDB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci"]
462
462
  end
463
463
 
464
464
  specify "should not use default if option has a nil value" do
465
465
  @db.create_table(:items, :engine=>nil, :charset=>nil, :collate=>nil){Integer :size; text :name}
466
- @db.sqls.should == ["CREATE TABLE items (size integer, name text)"]
466
+ @db.sqls.should == ["CREATE TABLE `items` (`size` integer, `name` text)"]
467
467
  end
468
468
  end
469
469
 
@@ -479,24 +479,24 @@ describe "A MySQL database" do
479
479
 
480
480
  specify "should support defaults for boolean columns" do
481
481
  @db.create_table(:items){TrueClass :active1, :default=>true; FalseClass :active2, :default => false}
482
- @db.sqls.should == ["CREATE TABLE items (active1 tinyint(1) DEFAULT 1, active2 tinyint(1) DEFAULT 0)"]
482
+ @db.sqls.should == ["CREATE TABLE `items` (`active1` tinyint(1) DEFAULT 1, `active2` tinyint(1) DEFAULT 0)"]
483
483
  end
484
484
 
485
485
  specify "should correctly format CREATE TABLE statements with foreign keys" do
486
486
  @db.create_table(:items){Integer :id; foreign_key :p_id, :items, :key => :id, :null => false, :on_delete => :cascade}
487
- @db.sqls.should == ["CREATE TABLE items (id integer, p_id integer NOT NULL, FOREIGN KEY (p_id) REFERENCES items(id) ON DELETE CASCADE)"]
487
+ @db.sqls.should == ["CREATE TABLE `items` (`id` integer, `p_id` integer NOT NULL, FOREIGN KEY (`p_id`) REFERENCES `items`(`id`) ON DELETE CASCADE)"]
488
488
  end
489
489
 
490
490
  specify "should correctly format ALTER TABLE statements with foreign keys" do
491
491
  @db.create_table(:items){Integer :id}
492
492
  @db.alter_table(:items){add_foreign_key :p_id, :users, :key => :id, :null => false, :on_delete => :cascade}
493
- @db.sqls.should == ["CREATE TABLE items (id integer)", "ALTER TABLE items ADD COLUMN p_id integer NOT NULL", "ALTER TABLE items ADD FOREIGN KEY (p_id) REFERENCES users(id) ON DELETE CASCADE"]
493
+ @db.sqls.should == ["CREATE TABLE `items` (`id` integer)", "ALTER TABLE `items` ADD COLUMN `p_id` integer NOT NULL", "ALTER TABLE `items` ADD FOREIGN KEY (`p_id`) REFERENCES `users`(`id`) ON DELETE CASCADE"]
494
494
  end
495
495
 
496
496
  specify "should have rename_column support keep existing options" do
497
497
  @db.create_table(:items){String :id, :null=>false, :default=>'blah'}
498
498
  @db.alter_table(:items){rename_column :id, :nid}
499
- @db.sqls.should == ["CREATE TABLE items (id varchar(255) NOT NULL DEFAULT 'blah')", "DESCRIBE items", "ALTER TABLE items CHANGE COLUMN id nid varchar(255) NOT NULL DEFAULT 'blah'"]
499
+ @db.sqls.should == ["CREATE TABLE `items` (`id` varchar(255) NOT NULL DEFAULT 'blah')", "DESCRIBE `items`", "ALTER TABLE `items` CHANGE COLUMN `id` `nid` varchar(255) NOT NULL DEFAULT 'blah'"]
500
500
  @db[:items].insert
501
501
  @db[:items].all.should == [{:nid=>'blah'}]
502
502
  proc{@db[:items].insert(:nid=>nil)}.should raise_error(Sequel::DatabaseError)
@@ -505,7 +505,7 @@ describe "A MySQL database" do
505
505
  specify "should have set_column_type support keep existing options" do
506
506
  @db.create_table(:items){Integer :id, :null=>false, :default=>5}
507
507
  @db.alter_table(:items){set_column_type :id, Bignum}
508
- @db.sqls.should == ["CREATE TABLE items (id integer NOT NULL DEFAULT 5)", "DESCRIBE items", "ALTER TABLE items CHANGE COLUMN id id bigint NOT NULL DEFAULT 5"]
508
+ @db.sqls.should == ["CREATE TABLE `items` (`id` integer NOT NULL DEFAULT 5)", "DESCRIBE `items`", "ALTER TABLE `items` CHANGE COLUMN `id` `id` bigint NOT NULL DEFAULT 5"]
509
509
  @db[:items].insert
510
510
  @db[:items].all.should == [{:id=>5}]
511
511
  proc{@db[:items].insert(:id=>nil)}.should raise_error(Sequel::DatabaseError)
@@ -517,13 +517,13 @@ describe "A MySQL database" do
517
517
  specify "should have set_column_type pass through options" do
518
518
  @db.create_table(:items){integer :id; enum :list, :elements=>%w[one]}
519
519
  @db.alter_table(:items){set_column_type :id, :int, :unsigned=>true, :size=>8; set_column_type :list, :enum, :elements=>%w[two]}
520
- @db.sqls.should == ["CREATE TABLE items (id integer, list enum('one'))", "DESCRIBE items", "ALTER TABLE items CHANGE COLUMN id id int(8) UNSIGNED NULL", "ALTER TABLE items CHANGE COLUMN list list enum('two') NULL"]
520
+ @db.sqls.should == ["CREATE TABLE `items` (`id` integer, `list` enum('one'))", "DESCRIBE `items`", "ALTER TABLE `items` CHANGE COLUMN `id` `id` int(8) UNSIGNED NULL", "ALTER TABLE `items` CHANGE COLUMN `list` `list` enum('two') NULL"]
521
521
  end
522
522
 
523
523
  specify "should have set_column_default support keep existing options" do
524
524
  @db.create_table(:items){Integer :id, :null=>false, :default=>5}
525
525
  @db.alter_table(:items){set_column_default :id, 6}
526
- @db.sqls.should == ["CREATE TABLE items (id integer NOT NULL DEFAULT 5)", "DESCRIBE items", "ALTER TABLE items CHANGE COLUMN id id int(11) NOT NULL DEFAULT 6"]
526
+ @db.sqls.should == ["CREATE TABLE `items` (`id` integer NOT NULL DEFAULT 5)", "DESCRIBE `items`", "ALTER TABLE `items` CHANGE COLUMN `id` `id` int(11) NOT NULL DEFAULT 6"]
527
527
  @db[:items].insert
528
528
  @db[:items].all.should == [{:id=>6}]
529
529
  proc{@db[:items].insert(:id=>nil)}.should raise_error(Sequel::DatabaseError)
@@ -532,7 +532,7 @@ describe "A MySQL database" do
532
532
  specify "should have set_column_allow_null support keep existing options" do
533
533
  @db.create_table(:items){Integer :id, :null=>false, :default=>5}
534
534
  @db.alter_table(:items){set_column_allow_null :id, true}
535
- @db.sqls.should == ["CREATE TABLE items (id integer NOT NULL DEFAULT 5)", "DESCRIBE items", "ALTER TABLE items CHANGE COLUMN id id int(11) NULL DEFAULT 5"]
535
+ @db.sqls.should == ["CREATE TABLE `items` (`id` integer NOT NULL DEFAULT 5)", "DESCRIBE `items`", "ALTER TABLE `items` CHANGE COLUMN `id` `id` int(11) NULL DEFAULT 5"]
536
536
  @db[:items].insert
537
537
  @db[:items].all.should == [{:id=>5}]
538
538
  proc{@db[:items].insert(:id=>nil)}.should_not
@@ -618,9 +618,9 @@ describe "A MySQL database" do
618
618
  specify "should support fulltext indexes and full_text_search" do
619
619
  @db.create_table(:posts){text :title; text :body; full_text_index :title; full_text_index [:title, :body]}
620
620
  @db.sqls.should == [
621
- "CREATE TABLE posts (title text, body text)",
622
- "CREATE FULLTEXT INDEX posts_title_index ON posts (title)",
623
- "CREATE FULLTEXT INDEX posts_title_body_index ON posts (title, body)"
621
+ "CREATE TABLE `posts` (`title` text, `body` text)",
622
+ "CREATE FULLTEXT INDEX `posts_title_index` ON `posts` (`title`)",
623
+ "CREATE FULLTEXT INDEX `posts_title_body_index` ON `posts` (`title`, `body`)"
624
624
  ]
625
625
 
626
626
  @db[:posts].insert(:title=>'ruby rails', :body=>'y')
@@ -632,32 +632,32 @@ describe "A MySQL database" do
632
632
  @db[:posts].full_text_search([:title, :body], ['sequel', 'ruby']).all.should == [{:title=>'sequel', :body=>'ruby'}]
633
633
  @db[:posts].full_text_search(:title, '+ruby -rails', :boolean => true).all.should == [{:title=>'ruby scooby', :body=>'x'}]
634
634
  @db.sqls.should == [
635
- "SELECT * FROM posts WHERE (MATCH (title) AGAINST ('rails'))",
636
- "SELECT * FROM posts WHERE (MATCH (title, body) AGAINST ('sequel ruby'))",
637
- "SELECT * FROM posts WHERE (MATCH (title) AGAINST ('+ruby -rails' IN BOOLEAN MODE))"]
635
+ "SELECT * FROM `posts` WHERE (MATCH (`title`) AGAINST ('rails'))",
636
+ "SELECT * FROM `posts` WHERE (MATCH (`title`, `body`) AGAINST ('sequel ruby'))",
637
+ "SELECT * FROM `posts` WHERE (MATCH (`title`) AGAINST ('+ruby -rails' IN BOOLEAN MODE))"]
638
638
  end
639
639
 
640
640
  specify "should support spatial indexes" do
641
641
  @db.create_table(:posts){point :geom, :null=>false; spatial_index [:geom]}
642
642
  @db.sqls.should == [
643
- "CREATE TABLE posts (geom point NOT NULL)",
644
- "CREATE SPATIAL INDEX posts_geom_index ON posts (geom)"
643
+ "CREATE TABLE `posts` (`geom` point NOT NULL)",
644
+ "CREATE SPATIAL INDEX `posts_geom_index` ON `posts` (`geom`)"
645
645
  ]
646
646
  end
647
647
 
648
648
  specify "should support indexes with index type" do
649
649
  @db.create_table(:posts){Integer :id; index :id, :type => :btree}
650
650
  @db.sqls.should == [
651
- "CREATE TABLE posts (id integer)",
652
- "CREATE INDEX posts_id_index USING btree ON posts (id)"
651
+ "CREATE TABLE `posts` (`id` integer)",
652
+ "CREATE INDEX `posts_id_index` USING btree ON `posts` (`id`)"
653
653
  ]
654
654
  end
655
655
 
656
656
  specify "should support unique indexes with index type" do
657
657
  @db.create_table(:posts){Integer :id; index :id, :type => :btree, :unique => true}
658
658
  @db.sqls.should == [
659
- "CREATE TABLE posts (id integer)",
660
- "CREATE UNIQUE INDEX posts_id_index USING btree ON posts (id)"
659
+ "CREATE TABLE `posts` (`id` integer)",
660
+ "CREATE UNIQUE INDEX `posts_id_index` USING btree ON `posts` (`id`)"
661
661
  ]
662
662
  end
663
663
 
@@ -686,38 +686,20 @@ describe "MySQL::Dataset#insert and related methods" do
686
686
 
687
687
  specify "#insert should insert record with default values when no arguments given" do
688
688
  @d.insert
689
-
690
- MYSQL_DB.sqls.should == [
691
- "INSERT INTO items () VALUES ()"
692
- ]
693
-
694
- @d.all.should == [
695
- {:name => nil, :value => nil}
696
- ]
689
+ MYSQL_DB.sqls.should == ["INSERT INTO `items` () VALUES ()"]
690
+ @d.all.should == [{:name => nil, :value => nil}]
697
691
  end
698
692
 
699
693
  specify "#insert should insert record with default values when empty hash given" do
700
694
  @d.insert({})
701
-
702
- MYSQL_DB.sqls.should == [
703
- "INSERT INTO items () VALUES ()"
704
- ]
705
-
706
- @d.all.should == [
707
- {:name => nil, :value => nil}
708
- ]
695
+ MYSQL_DB.sqls.should == ["INSERT INTO `items` () VALUES ()"]
696
+ @d.all.should == [{:name => nil, :value => nil}]
709
697
  end
710
698
 
711
699
  specify "#insert should insert record with default values when empty array given" do
712
700
  @d.insert []
713
-
714
- MYSQL_DB.sqls.should == [
715
- "INSERT INTO items () VALUES ()"
716
- ]
717
-
718
- @d.all.should == [
719
- {:name => nil, :value => nil}
720
- ]
701
+ MYSQL_DB.sqls.should == ["INSERT INTO `items` () VALUES ()"]
702
+ @d.all.should == [{:name => nil, :value => nil}]
721
703
  end
722
704
 
723
705
  specify "#on_duplicate_key_update should work with regular inserts" do
@@ -728,9 +710,9 @@ describe "MySQL::Dataset#insert and related methods" do
728
710
  @d.on_duplicate_key_update(:name, :value => 6).insert(:name => 'def', :value => 2)
729
711
 
730
712
  MYSQL_DB.sqls.length.should == 3
731
- MYSQL_DB.sqls[0].should =~ /\AINSERT INTO items \((name|value), (name|value)\) VALUES \(('abc'|1), (1|'abc')\)\z/
732
- MYSQL_DB.sqls[1].should =~ /\AINSERT INTO items \((name|value), (name|value)\) VALUES \(('abc'|1), (1|'abc')\) ON DUPLICATE KEY UPDATE name=VALUES\(name\), value=6\z/
733
- MYSQL_DB.sqls[2].should =~ /\AINSERT INTO items \((name|value), (name|value)\) VALUES \(('def'|2), (2|'def')\) ON DUPLICATE KEY UPDATE name=VALUES\(name\), value=6\z/
713
+ MYSQL_DB.sqls[0].should =~ /\AINSERT INTO `items` \(`(name|value)`, `(name|value)`\) VALUES \(('abc'|1), (1|'abc')\)\z/
714
+ MYSQL_DB.sqls[1].should =~ /\AINSERT INTO `items` \(`(name|value)`, `(name|value)`\) VALUES \(('abc'|1), (1|'abc')\) ON DUPLICATE KEY UPDATE `name`=VALUES\(`name`\), `value`=6\z/
715
+ MYSQL_DB.sqls[2].should =~ /\AINSERT INTO `items` \(`(name|value)`, `(name|value)`\) VALUES \(('def'|2), (2|'def')\) ON DUPLICATE KEY UPDATE `name`=VALUES\(`name`\), `value`=6\z/
734
716
 
735
717
  @d.all.should == [{:name => 'abc', :value => 6}, {:name => 'def', :value => 2}]
736
718
  end
@@ -740,7 +722,7 @@ describe "MySQL::Dataset#insert and related methods" do
740
722
 
741
723
  MYSQL_DB.sqls.should == [
742
724
  SQL_BEGIN,
743
- "INSERT INTO items (name) VALUES ('abc'), ('def')",
725
+ "INSERT INTO `items` (`name`) VALUES ('abc'), ('def')",
744
726
  SQL_COMMIT
745
727
  ]
746
728
 
@@ -755,10 +737,10 @@ describe "MySQL::Dataset#insert and related methods" do
755
737
 
756
738
  MYSQL_DB.sqls.should == [
757
739
  SQL_BEGIN,
758
- "INSERT INTO items (value) VALUES (1), (2)",
740
+ "INSERT INTO `items` (`value`) VALUES (1), (2)",
759
741
  SQL_COMMIT,
760
742
  SQL_BEGIN,
761
- "INSERT INTO items (value) VALUES (3), (4)",
743
+ "INSERT INTO `items` (`value`) VALUES (3), (4)",
762
744
  SQL_COMMIT
763
745
  ]
764
746
 
@@ -776,10 +758,10 @@ describe "MySQL::Dataset#insert and related methods" do
776
758
 
777
759
  MYSQL_DB.sqls.should == [
778
760
  SQL_BEGIN,
779
- "INSERT INTO items (value) VALUES (1), (2)",
761
+ "INSERT INTO `items` (`value`) VALUES (1), (2)",
780
762
  SQL_COMMIT,
781
763
  SQL_BEGIN,
782
- "INSERT INTO items (value) VALUES (3), (4)",
764
+ "INSERT INTO `items` (`value`) VALUES (3), (4)",
783
765
  SQL_COMMIT
784
766
  ]
785
767
 
@@ -796,7 +778,7 @@ describe "MySQL::Dataset#insert and related methods" do
796
778
 
797
779
  MYSQL_DB.sqls.should == [
798
780
  SQL_BEGIN,
799
- "INSERT INTO items (name, value) VALUES ('abc', 1), ('def', 2)",
781
+ "INSERT INTO `items` (`name`, `value`) VALUES ('abc', 1), ('def', 2)",
800
782
  SQL_COMMIT
801
783
  ]
802
784
 
@@ -811,7 +793,7 @@ describe "MySQL::Dataset#insert and related methods" do
811
793
 
812
794
  MYSQL_DB.sqls.should == [
813
795
  SQL_BEGIN,
814
- "INSERT IGNORE INTO items (name) VALUES ('abc'), ('def')",
796
+ "INSERT IGNORE INTO `items` (`name`) VALUES ('abc'), ('def')",
815
797
  SQL_COMMIT
816
798
  ]
817
799
 
@@ -822,7 +804,7 @@ describe "MySQL::Dataset#insert and related methods" do
822
804
 
823
805
  specify "#insert_ignore should add the IGNORE keyword for single inserts" do
824
806
  @d.insert_ignore.insert(:name => 'ghi')
825
- MYSQL_DB.sqls.should == ["INSERT IGNORE INTO items (name) VALUES ('ghi')"]
807
+ MYSQL_DB.sqls.should == ["INSERT IGNORE INTO `items` (`name`) VALUES ('ghi')"]
826
808
  @d.all.should == [{:name => 'ghi', :value => nil}]
827
809
  end
828
810
 
@@ -830,9 +812,9 @@ describe "MySQL::Dataset#insert and related methods" do
830
812
  @d.on_duplicate_key_update.import([:name,:value], [['abc', 1], ['def',2]])
831
813
 
832
814
  MYSQL_DB.sqls.should == [
833
- "SELECT * FROM items LIMIT 1",
815
+ "SELECT * FROM `items` LIMIT 1",
834
816
  SQL_BEGIN,
835
- "INSERT INTO items (name, value) VALUES ('abc', 1), ('def', 2) ON DUPLICATE KEY UPDATE name=VALUES(name), value=VALUES(value)",
817
+ "INSERT INTO `items` (`name`, `value`) VALUES ('abc', 1), ('def', 2) ON DUPLICATE KEY UPDATE `name`=VALUES(`name`), `value`=VALUES(`value`)",
836
818
  SQL_COMMIT
837
819
  ]
838
820
 
@@ -848,7 +830,7 @@ describe "MySQL::Dataset#insert and related methods" do
848
830
 
849
831
  MYSQL_DB.sqls.should == [
850
832
  SQL_BEGIN,
851
- "INSERT INTO items (name, value) VALUES ('abc', 1), ('def', 2) ON DUPLICATE KEY UPDATE value=VALUES(value)",
833
+ "INSERT INTO `items` (`name`, `value`) VALUES ('abc', 1), ('def', 2) ON DUPLICATE KEY UPDATE `value`=VALUES(`value`)",
852
834
  SQL_COMMIT
853
835
  ]
854
836
 
@@ -907,25 +889,25 @@ describe "MySQL::Dataset#complex_expression_sql" do
907
889
  end
908
890
 
909
891
  specify "should handle pattern matches correctly" do
910
- @d.literal(:x.like('a')).should == "(x LIKE BINARY 'a')"
911
- @d.literal(~:x.like('a')).should == "(x NOT LIKE BINARY 'a')"
912
- @d.literal(:x.ilike('a')).should == "(x LIKE 'a')"
913
- @d.literal(~:x.ilike('a')).should == "(x NOT LIKE 'a')"
914
- @d.literal(:x.like(/a/)).should == "(x REGEXP BINARY 'a')"
915
- @d.literal(~:x.like(/a/)).should == "(x NOT REGEXP BINARY 'a')"
916
- @d.literal(:x.like(/a/i)).should == "(x REGEXP 'a')"
917
- @d.literal(~:x.like(/a/i)).should == "(x NOT REGEXP 'a')"
892
+ @d.literal(:x.like('a')).should == "(`x` LIKE BINARY 'a')"
893
+ @d.literal(~:x.like('a')).should == "(`x` NOT LIKE BINARY 'a')"
894
+ @d.literal(:x.ilike('a')).should == "(`x` LIKE 'a')"
895
+ @d.literal(~:x.ilike('a')).should == "(`x` NOT LIKE 'a')"
896
+ @d.literal(:x.like(/a/)).should == "(`x` REGEXP BINARY 'a')"
897
+ @d.literal(~:x.like(/a/)).should == "(`x` NOT REGEXP BINARY 'a')"
898
+ @d.literal(:x.like(/a/i)).should == "(`x` REGEXP 'a')"
899
+ @d.literal(~:x.like(/a/i)).should == "(`x` NOT REGEXP 'a')"
918
900
  end
919
901
 
920
902
  specify "should handle string concatenation with CONCAT if more than one record" do
921
- @d.literal([:x, :y].sql_string_join).should == "CONCAT(x, y)"
922
- @d.literal([:x, :y].sql_string_join(' ')).should == "CONCAT(x, ' ', y)"
923
- @d.literal([:x.sql_function(:y), 1, 'z'.lit].sql_string_join(:y.sql_subscript(1))).should == "CONCAT(x(y), y[1], '1', y[1], z)"
903
+ @d.literal([:x, :y].sql_string_join).should == "CONCAT(`x`, `y`)"
904
+ @d.literal([:x, :y].sql_string_join(' ')).should == "CONCAT(`x`, ' ', `y`)"
905
+ @d.literal([:x.sql_function(:y), 1, 'z'.lit].sql_string_join(:y.sql_subscript(1))).should == "CONCAT(x(`y`), `y`[1], '1', `y`[1], z)"
924
906
  end
925
907
 
926
908
  specify "should handle string concatenation as simple string if just one record" do
927
- @d.literal([:x].sql_string_join).should == "x"
928
- @d.literal([:x].sql_string_join(' ')).should == "x"
909
+ @d.literal([:x].sql_string_join).should == "`x`"
910
+ @d.literal([:x].sql_string_join(' ')).should == "`x`"
929
911
  end
930
912
  end
931
913
 
@@ -939,7 +921,7 @@ describe "MySQL::Dataset#calc_found_rows" do
939
921
 
940
922
  specify "should add the SQL_CALC_FOUND_ROWS keyword when selecting" do
941
923
  MYSQL_DB[:items].select(:a).calc_found_rows.limit(1).sql.should == \
942
- 'SELECT SQL_CALC_FOUND_ROWS a FROM items LIMIT 1'
924
+ 'SELECT SQL_CALC_FOUND_ROWS `a` FROM `items` LIMIT 1'
943
925
  end
944
926
 
945
927
  specify "should count matching rows disregarding LIMIT clause" do
@@ -950,8 +932,8 @@ describe "MySQL::Dataset#calc_found_rows" do
950
932
  MYSQL_DB.dataset.select(:FOUND_ROWS.sql_function.as(:rows)).all.should == [{:rows => 2 }]
951
933
 
952
934
  MYSQL_DB.sqls.should == [
953
- 'SELECT SQL_CALC_FOUND_ROWS * FROM items WHERE (a = 1) LIMIT 1',
954
- 'SELECT FOUND_ROWS() AS rows',
935
+ 'SELECT SQL_CALC_FOUND_ROWS * FROM `items` WHERE (`a` = 1) LIMIT 1',
936
+ 'SELECT FOUND_ROWS() AS `rows`',
955
937
  ]
956
938
  end
957
939
  end
@@ -1015,29 +997,29 @@ end
1015
997
  if MYSQL_DB.adapter_scheme == :mysql
1016
998
  describe "MySQL bad date/time conversions" do
1017
999
  after do
1018
- Sequel::MySQL.convert_invalid_date_time = false
1000
+ MYSQL_DB.convert_invalid_date_time = false
1019
1001
  end
1020
1002
 
1021
1003
  specify "should raise an exception when a bad date/time is used and convert_invalid_date_time is false" do
1022
- Sequel::MySQL.convert_invalid_date_time = false
1004
+ MYSQL_DB.convert_invalid_date_time = false
1023
1005
  proc{MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value}.should raise_error(Sequel::InvalidValue)
1024
1006
  proc{MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value}.should raise_error(Sequel::InvalidValue)
1025
1007
  proc{MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value}.should raise_error(Sequel::InvalidValue)
1026
1008
  end
1027
1009
 
1028
1010
  specify "should not use a nil value bad date/time is used and convert_invalid_date_time is nil or :nil" do
1029
- Sequel::MySQL.convert_invalid_date_time = nil
1011
+ MYSQL_DB.convert_invalid_date_time = nil
1030
1012
  MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value.should == nil
1031
1013
  MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value.should == nil
1032
1014
  MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value.should == nil
1033
- Sequel::MySQL.convert_invalid_date_time = :nil
1015
+ MYSQL_DB.convert_invalid_date_time = :nil
1034
1016
  MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value.should == nil
1035
1017
  MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value.should == nil
1036
1018
  MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value.should == nil
1037
1019
  end
1038
1020
 
1039
1021
  specify "should not use a nil value bad date/time is used and convert_invalid_date_time is :string" do
1040
- Sequel::MySQL.convert_invalid_date_time = :string
1022
+ MYSQL_DB.convert_invalid_date_time = :string
1041
1023
  MYSQL_DB["SELECT CAST('0000-00-00' AS date)"].single_value.should == '0000-00-00'
1042
1024
  MYSQL_DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value.should == '0000-00-00 00:00:00'
1043
1025
  MYSQL_DB["SELECT CAST('25:00:00' AS time)"].single_value.should == '25:00:00'