activerecord-postgresql-extensions 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +16 -5
- data/activerecord-postgresql-extensions.gemspec +2 -0
- data/lib/active_record/postgresql_extensions/adapter_extensions.rb +14 -2
- data/lib/active_record/postgresql_extensions/constraints.rb +203 -13
- data/lib/active_record/postgresql_extensions/extensions.rb +18 -0
- data/lib/active_record/postgresql_extensions/features.rb +46 -0
- data/lib/active_record/postgresql_extensions/indexes.rb +16 -0
- data/lib/active_record/postgresql_extensions/permissions.rb +47 -22
- data/lib/active_record/postgresql_extensions/postgis.rb +6 -2
- data/lib/active_record/postgresql_extensions/tables.rb +45 -11
- data/lib/active_record/postgresql_extensions/vacuum.rb +101 -0
- data/lib/active_record/postgresql_extensions/version.rb +1 -1
- data/lib/activerecord-postgresql-extensions.rb +12 -0
- data/test/adapter_tests.rb +54 -2
- data/test/constraints_tests.rb +107 -1
- data/test/extensions_tests.rb +27 -1
- data/test/functions_tests.rb +1 -1
- data/test/geometry_tests.rb +180 -154
- data/test/index_tests.rb +12 -2
- data/test/languages_tests.rb +1 -1
- data/test/permissions_tests.rb +19 -7
- data/test/roles_tests.rb +1 -1
- data/test/rules_tests.rb +1 -1
- data/test/schemas_tests.rb +1 -1
- data/test/sequences_tests.rb +1 -1
- data/test/tables_tests.rb +16 -2
- data/test/tablespace_tests.rb +1 -1
- data/test/test_helper.rb +18 -3
- data/test/text_search_tests.rb +7 -7
- data/test/trigger_tests.rb +1 -1
- data/test/vacuum_tests.rb +39 -0
- metadata +38 -2
@@ -0,0 +1,46 @@
|
|
1
|
+
|
2
|
+
module ActiveRecord
|
3
|
+
module PostgreSQLExtensions
|
4
|
+
class FeatureNotSupportedError < Exception
|
5
|
+
def initialize(feature)
|
6
|
+
super(%{The feature "#{feature}" is not supported by server. (Server version #{ActiveRecord::PostgreSQLExtensions.SERVER_VERSION}.)"})
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module Features
|
11
|
+
class << self
|
12
|
+
def extensions?
|
13
|
+
if defined?(@has_extensions)
|
14
|
+
@has_extensions
|
15
|
+
else
|
16
|
+
@has_extensions = ActiveRecord::PostgreSQLExtensions.SERVER_VERSION >= '9.1'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def foreign_tables?
|
21
|
+
if defined?(@has_foreign_tables)
|
22
|
+
@has_foreign_tables
|
23
|
+
else
|
24
|
+
@has_foreign_tables = ActiveRecord::PostgreSQLExtensions.SERVER_VERSION >= '9.1'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def modify_mass_privileges?
|
29
|
+
if defined?(@has_modify_mass_privileges)
|
30
|
+
@has_modify_mass_privileges
|
31
|
+
else
|
32
|
+
@has_modify_mass_privileges = ActiveRecord::PostgreSQLExtensions.SERVER_VERSION >= '9.0'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def postgis?
|
37
|
+
if defined?(@has_postgis)
|
38
|
+
@has_postgis
|
39
|
+
else
|
40
|
+
@has_postgis = !!ActiveRecord::PostgreSQLExtensions::PostGIS.VERSION
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -117,12 +117,28 @@ module ActiveRecord
|
|
117
117
|
# name with drop_index. See create_index for the particulars on
|
118
118
|
# why.
|
119
119
|
#
|
120
|
+
# You can specify multiple INDEXes with an Array when using drop_index,
|
121
|
+
# but you may need to use the method directly through the ActiveRecord
|
122
|
+
# connection rather than the Migration method, as the Migration method
|
123
|
+
# likes to escape the Array to a String.
|
124
|
+
#
|
120
125
|
# ==== Options
|
121
126
|
#
|
122
127
|
# * <tt>:if_exists</tt> - adds IF EXISTS.
|
123
128
|
# * <tt>:cascade</tt> - adds CASCADE.
|
129
|
+
# * <tt>:concurrently</tt> - adds the CONCURRENTLY option when dropping
|
130
|
+
# the INDEX. When using the :concurrently option, only one INDEX can
|
131
|
+
# specified and the :cascade option cannot be used. See the PostgreSQL
|
132
|
+
# documentation for details.
|
124
133
|
def drop_index(name, options = {})
|
134
|
+
if options[:concurrently] && options[:cascade]
|
135
|
+
raise ArgumentError.new("The :concurrently and :cascade options cannot be used together.")
|
136
|
+
elsif options[:concurrently] && name.is_a?(Array) && name.length > 1
|
137
|
+
raise ArgumentError.new("The :concurrently option can only be used on a single INDEX.")
|
138
|
+
end
|
139
|
+
|
125
140
|
sql = 'DROP INDEX '
|
141
|
+
sql << 'CONCURRENTLY ' if options[:concurrently]
|
126
142
|
sql << 'IF EXISTS ' if options[:if_exists]
|
127
143
|
sql << Array(name).collect { |i| quote_generic(i) }.join(', ')
|
128
144
|
sql << ' CASCADE' if options[:cascade]
|
@@ -200,7 +200,9 @@ module ActiveRecord
|
|
200
200
|
#
|
201
201
|
# When using the grant_*_privileges methods, you can specify multiple
|
202
202
|
# permissions, objects and roles by using Arrays for the appropriate
|
203
|
-
# argument.
|
203
|
+
# argument. You can also apply the privileges to all objects within a
|
204
|
+
# schema by using the :all option in the options Hash and supply the schema
|
205
|
+
# name as the first argument.
|
204
206
|
#
|
205
207
|
# ==== Examples
|
206
208
|
#
|
@@ -210,6 +212,9 @@ module ActiveRecord
|
|
210
212
|
# grant_sequence_privileges(:my_seq, [ :select, :update ], :public)
|
211
213
|
# # => GRANT SELECT, UPDATE ON SEQUENCE "my_seq" TO PUBLIC
|
212
214
|
#
|
215
|
+
# grant_sequence_privileges(:public, [ :select, :update ], :joe, :all => true)
|
216
|
+
# # => GRANT SELECT, UPDATE ON ALL SEQUENCES IN SCHEMA PUBLIC TO "joe"
|
217
|
+
#
|
213
218
|
# You can specify the <tt>:with_grant_option</tt> in any of the
|
214
219
|
# grant_*_privilege methods to add a WITH GRANT OPTION clause to
|
215
220
|
# the command.
|
@@ -219,19 +224,28 @@ module ActiveRecord
|
|
219
224
|
:quote_objects => true
|
220
225
|
}.merge query_options
|
221
226
|
|
222
|
-
sql = "GRANT #{Array(privileges).collect(&:to_s).collect(&:upcase).join(', ')} ON
|
227
|
+
sql = "GRANT #{Array(privileges).collect(&:to_s).collect(&:upcase).join(', ')} ON "
|
228
|
+
|
229
|
+
if options[:all]
|
230
|
+
if !ActiveRecord::PostgreSQLExtensions::Features.modify_mass_privileges?
|
231
|
+
raise ActiveRecord::PostgreSQLExtensions::FeatureNotSupportedError.new('modify mass privileges')
|
232
|
+
end
|
223
233
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
234
|
+
sql << "ALL #{type.to_s.upcase}S IN SCHEMA #{base.quote_schema(objects)}"
|
235
|
+
else
|
236
|
+
sql << "#{type.to_s.upcase} "
|
237
|
+
sql << Array(objects).collect do |t|
|
238
|
+
if my_query_options[:quote_objects]
|
239
|
+
if my_query_options[:ignore_schema]
|
240
|
+
base.quote_generic_ignore_scoped_schema(t)
|
241
|
+
else
|
242
|
+
base.quote_table_name(t)
|
243
|
+
end
|
228
244
|
else
|
229
|
-
|
245
|
+
t
|
230
246
|
end
|
231
|
-
|
232
|
-
|
233
|
-
end
|
234
|
-
end.join(', ')
|
247
|
+
end.join(', ')
|
248
|
+
end
|
235
249
|
|
236
250
|
sql << ' TO ' << Array(roles).collect do |r|
|
237
251
|
r = r.to_s
|
@@ -259,7 +273,9 @@ module ActiveRecord
|
|
259
273
|
#
|
260
274
|
# When using the revoke_*_privileges methods, you can specify multiple
|
261
275
|
# permissions, objects and roles by using Arrays for the appropriate
|
262
|
-
# argument.
|
276
|
+
# argument. You can also apply the privileges to all objects within a
|
277
|
+
# schema by using the :all option in the options Hash and supply the schema
|
278
|
+
# name as the first argument.
|
263
279
|
#
|
264
280
|
# ==== Examples
|
265
281
|
#
|
@@ -288,19 +304,28 @@ module ActiveRecord
|
|
288
304
|
|
289
305
|
sql = 'REVOKE '
|
290
306
|
sql << 'GRANT OPTION FOR ' if options[:grant_option_for]
|
291
|
-
sql << "#{Array(privileges).collect(&:to_s).collect(&:upcase).join(', ')} ON
|
307
|
+
sql << "#{Array(privileges).collect(&:to_s).collect(&:upcase).join(', ')} ON "
|
292
308
|
|
293
|
-
|
294
|
-
if
|
295
|
-
|
296
|
-
|
309
|
+
if options[:all]
|
310
|
+
if !ActiveRecord::PostgreSQLExtensions::Features.modify_mass_privileges?
|
311
|
+
raise ActiveRecord::PostgreSQLExtensions::FeatureNotSupportedError.new('modify mass privileges')
|
312
|
+
end
|
313
|
+
|
314
|
+
sql << "ALL #{type.to_s.upcase}S IN SCHEMA #{base.quote_schema(objects)}"
|
315
|
+
else
|
316
|
+
sql << "#{type.to_s.upcase} "
|
317
|
+
sql << Array(objects).collect do |t|
|
318
|
+
if my_query_options[:quote_objects]
|
319
|
+
if my_query_options[:ignore_schema]
|
320
|
+
base.quote_generic_ignore_scoped_schema(t)
|
321
|
+
else
|
322
|
+
base.quote_table_name(t)
|
323
|
+
end
|
297
324
|
else
|
298
|
-
|
325
|
+
t
|
299
326
|
end
|
300
|
-
|
301
|
-
|
302
|
-
end
|
303
|
-
end.join(', ')
|
327
|
+
end.join(', ')
|
328
|
+
end
|
304
329
|
|
305
330
|
sql << ' FROM ' << Array(roles).collect do |r|
|
306
331
|
r = r.to_s
|
@@ -29,7 +29,9 @@ module ActiveRecord
|
|
29
29
|
def UNKNOWN_SRIDS
|
30
30
|
return @UNKNOWN_SRIDS if defined?(@UNKNOWN_SRIDS)
|
31
31
|
|
32
|
-
@UNKNOWN_SRIDS = if self.VERSION
|
32
|
+
@UNKNOWN_SRIDS = if !self.VERSION
|
33
|
+
nil
|
34
|
+
elsif self.VERSION[:lib] >= '2.0'
|
33
35
|
{
|
34
36
|
:geography => 0,
|
35
37
|
:geometry => 0
|
@@ -45,7 +47,9 @@ module ActiveRecord
|
|
45
47
|
def UNKNOWN_SRID
|
46
48
|
return @UNKNOWN_SRID if defined?(@UNKNOWN_SRID)
|
47
49
|
|
48
|
-
@UNKNOWN_SRID = self.UNKNOWN_SRIDS
|
50
|
+
@UNKNOWN_SRID = if self.UNKNOWN_SRIDS
|
51
|
+
self.UNKNOWN_SRIDS[:geometry]
|
52
|
+
end
|
49
53
|
end
|
50
54
|
end
|
51
55
|
end
|
@@ -178,27 +178,48 @@ module ActiveRecord
|
|
178
178
|
@table_constraints = Array.new
|
179
179
|
@table_name, @options = table_name, options
|
180
180
|
super(base)
|
181
|
-
|
182
|
-
self.primary_key(
|
183
|
-
options[:primary_key] || Base.get_primary_key(table_name)
|
184
|
-
) unless options[:id] == false
|
185
181
|
end
|
186
182
|
|
187
183
|
def to_sql #:nodoc:
|
184
|
+
if self.options[:of_type]
|
185
|
+
if !@columns.empty?
|
186
|
+
raise ArgumentError.new("Cannot specify columns while using the :of_type option")
|
187
|
+
elsif options[:like]
|
188
|
+
raise ArgumentError.new("Cannot specify both the :like and :of_type options")
|
189
|
+
elsif options[:inherits]
|
190
|
+
raise ArgumentError.new("Cannot specify both the :inherits and :of_type options")
|
191
|
+
else
|
192
|
+
options[:id] = false
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
unless options[:id] == false
|
197
|
+
self.primary_key(options[:primary_key] || Base.get_primary_key(table_name))
|
198
|
+
|
199
|
+
# ensures that the primary key column is first.
|
200
|
+
@columns.unshift(@columns.pop)
|
201
|
+
end
|
202
|
+
|
188
203
|
sql = 'CREATE '
|
189
204
|
sql << 'TEMPORARY ' if options[:temporary]
|
190
205
|
sql << 'UNLOGGED ' if options[:unlogged]
|
191
206
|
sql << 'TABLE '
|
192
207
|
sql << 'IF NOT EXISTS ' if options[:if_not_exists]
|
193
|
-
sql << "#{base.quote_table_name(table_name)}
|
194
|
-
sql << "OF #{base.quote_table_name(options[:of_type])}
|
195
|
-
sql << "(\n "
|
208
|
+
sql << "#{base.quote_table_name(table_name)}"
|
209
|
+
sql << " OF #{base.quote_table_name(options[:of_type])}" if options[:of_type]
|
196
210
|
|
197
|
-
ary =
|
198
|
-
|
211
|
+
ary = []
|
212
|
+
if !options[:of_type]
|
213
|
+
ary << @columns.collect(&:to_sql)
|
214
|
+
ary << @like if defined?(@like) && @like
|
215
|
+
end
|
199
216
|
ary << @table_constraints unless @table_constraints.empty?
|
200
|
-
|
201
|
-
|
217
|
+
|
218
|
+
unless ary.empty?
|
219
|
+
sql << " (\n "
|
220
|
+
sql << ary * ",\n "
|
221
|
+
sql << "\n)"
|
222
|
+
end
|
202
223
|
|
203
224
|
sql << "\nINHERITS (" << Array(options[:inherits]).collect { |i| base.quote_table_name(i) }.join(', ') << ')' if options[:inherits]
|
204
225
|
sql << "\nON COMMIT #{options[:on_commit].to_s.upcase.gsub(/_/, ' ')}" if options[:on_commit]
|
@@ -265,11 +286,16 @@ module ActiveRecord
|
|
265
286
|
@table_constraints << PostgreSQLExcludeConstraint.new(@base, table_name, excludes, options)
|
266
287
|
end
|
267
288
|
|
289
|
+
def primary_key_constraint(columns, options = {})
|
290
|
+
@table_constraints << PostgreSQLPrimaryKeyConstraint.new(@base, columns, options)
|
291
|
+
end
|
292
|
+
|
268
293
|
def column_with_constraints(name, type, *args) #:nodoc:
|
269
294
|
options = args.extract_options!
|
270
295
|
check = options.delete(:check)
|
271
296
|
references = options.delete(:references)
|
272
297
|
unique = options.delete(:unique)
|
298
|
+
primary_key = options.delete(:primary_key)
|
273
299
|
column_without_constraints(name, type, options)
|
274
300
|
|
275
301
|
if check
|
@@ -309,6 +335,14 @@ module ActiveRecord
|
|
309
335
|
end
|
310
336
|
@table_constraints << PostgreSQLUniqueConstraint.new(@base, name, unique)
|
311
337
|
end
|
338
|
+
|
339
|
+
if primary_key
|
340
|
+
unless primary_key.is_a?(Hash)
|
341
|
+
primary_key = {}
|
342
|
+
end
|
343
|
+
@table_constraints << PostgreSQLPrimaryKeyConstraint.new(@base, name, primary_key)
|
344
|
+
end
|
345
|
+
|
312
346
|
self
|
313
347
|
end
|
314
348
|
alias_method_chain :column, :constraints
|
@@ -0,0 +1,101 @@
|
|
1
|
+
|
2
|
+
require 'active_record/connection_adapters/postgresql_adapter'
|
3
|
+
|
4
|
+
module ActiveRecord
|
5
|
+
module ConnectionAdapters
|
6
|
+
class PostgreSQLAdapter
|
7
|
+
# VACUUMs a database, table or columns on a table. See
|
8
|
+
# PostgreSQLVacuum for details.
|
9
|
+
def vacuum(*args)
|
10
|
+
vacuumer = PostgreSQLVacuum.new(self, *args)
|
11
|
+
execute("#{vacuumer};")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Creates queries for invoking VACUUM.
|
16
|
+
#
|
17
|
+
# This class is meant to be used by the PostgreSQLAdapter#vacuum method.
|
18
|
+
# VACUUMs can be performed against the database as a whole, on specific
|
19
|
+
# tables or on specific columns.
|
20
|
+
#
|
21
|
+
# ==== Examples
|
22
|
+
#
|
23
|
+
# ActiveRecord::Base.connection.vacuum
|
24
|
+
# # => VACUUM;
|
25
|
+
#
|
26
|
+
# ActiveRecord::Base.connection.vacuum(:full => true, :analyze => true)
|
27
|
+
# # => VACUUM FULL; # PostgreSQL < 9.0
|
28
|
+
# # => VACUUM (FULL); # PostgreSQL >= 9.0
|
29
|
+
#
|
30
|
+
# ActiveRecord::Base.connection.vacuum(:foos)
|
31
|
+
# # => VACUUM "foos";
|
32
|
+
#
|
33
|
+
# ActiveRecord::Base.connection.vacuum(:foos, :columns => [ :bar, :baz ])
|
34
|
+
# # => VACUUM (ANALYZE) "foos" ("bar", "baz");
|
35
|
+
#
|
36
|
+
# ==== Options
|
37
|
+
#
|
38
|
+
# * <tt>:full</tt>, <tt>:freeze</tt>, <tt>:verbose</tt> and
|
39
|
+
# <tt>:analyze</tt> are all supported.
|
40
|
+
# * <tt>:columns</tt> - specifies the columns to VACUUM. You must specify
|
41
|
+
# a table when using this option. This option also forces the :analyze
|
42
|
+
# option to true, as PostgreSQL doesn't like to try and VACUUM a column
|
43
|
+
# without analyzing it.
|
44
|
+
class PostgreSQLVacuum
|
45
|
+
VACUUM_OPTIONS = %w{
|
46
|
+
FULL FREEZE VERBOSE ANALYZE
|
47
|
+
}.freeze
|
48
|
+
|
49
|
+
attr_accessor :base, :table, :options
|
50
|
+
|
51
|
+
def initialize(base, *args)
|
52
|
+
if !args.length.between?(0, 2)
|
53
|
+
raise ArgumentError.new("Wrong number of arguments #{args.length} for 0-2")
|
54
|
+
end
|
55
|
+
|
56
|
+
options = args.extract_options!
|
57
|
+
table = args.first
|
58
|
+
|
59
|
+
if options[:columns]
|
60
|
+
if !table
|
61
|
+
raise ArgumentError.new("You must specify a table when using the :columns option.")
|
62
|
+
end
|
63
|
+
|
64
|
+
options[:analyze] = true
|
65
|
+
end
|
66
|
+
|
67
|
+
@base, @table, @options = base, table, options
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_sql
|
71
|
+
vacuum_options = VACUUM_OPTIONS.select { |o|
|
72
|
+
o = o.downcase.to_sym
|
73
|
+
self.options[o.to_sym]
|
74
|
+
}
|
75
|
+
|
76
|
+
sql = 'VACUUM'
|
77
|
+
|
78
|
+
if !vacuum_options.empty?
|
79
|
+
sql << if ActiveRecord::PostgreSQLExtensions.SERVER_VERSION.to_f >= 9.0
|
80
|
+
" (#{vacuum_options.join(', ')})"
|
81
|
+
else
|
82
|
+
' ' << VACUUM_OPTIONS.collect { |v|
|
83
|
+
v.upcase if vacuum_options.include?(v)
|
84
|
+
}.compact.join(' ')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
sql << " #{base.quote_table_name(table)}" if self.table
|
89
|
+
|
90
|
+
if options[:columns]
|
91
|
+
sql << ' (' << Array(options[:columns]).collect { |column|
|
92
|
+
base.quote_column_name(column)
|
93
|
+
}.join(', ') << ')'
|
94
|
+
end
|
95
|
+
|
96
|
+
sql
|
97
|
+
end
|
98
|
+
alias :to_s :to_sql
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -3,12 +3,23 @@ require 'active_record/connection_adapters/postgresql_adapter'
|
|
3
3
|
|
4
4
|
module ActiveRecord
|
5
5
|
module PostgreSQLExtensions
|
6
|
+
class << self
|
7
|
+
def SERVER_VERSION
|
8
|
+
return @SERVER_VERSION if defined?(@SERVER_VERSION)
|
9
|
+
|
10
|
+
@SERVER_VERSION = if (version_string = ::ActiveRecord::Base.connection.select_rows("SELECT pg_catalog.version()").flatten.first).present?
|
11
|
+
version_string =~ /^\s*PostgreSQL\s+([^\s]+)/
|
12
|
+
$1
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
6
16
|
end
|
7
17
|
end
|
8
18
|
|
9
19
|
dirname = File.join(File.dirname(__FILE__), *%w{ active_record postgresql_extensions })
|
10
20
|
|
11
21
|
%w{
|
22
|
+
features
|
12
23
|
adapter_extensions
|
13
24
|
constraints
|
14
25
|
tables
|
@@ -28,6 +39,7 @@ dirname = File.join(File.dirname(__FILE__), *%w{ active_record postgresql_extens
|
|
28
39
|
text_search
|
29
40
|
extensions
|
30
41
|
foreign_key_associations
|
42
|
+
vacuum
|
31
43
|
}.each do |file|
|
32
44
|
require File.join(dirname, file)
|
33
45
|
end
|
data/test/adapter_tests.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
$: << File.dirname(__FILE__)
|
3
3
|
require 'test_helper'
|
4
4
|
|
5
|
-
class AdapterExtensionTests <
|
5
|
+
class AdapterExtensionTests < MiniTest::Unit::TestCase
|
6
6
|
include PostgreSQLExtensionsTestHelper
|
7
7
|
|
8
8
|
def test_quote_table_name_with_schema_string
|
@@ -62,7 +62,7 @@ class AdapterExtensionTests < Test::Unit::TestCase
|
|
62
62
|
%{SET SESSION ROLE "foo";}
|
63
63
|
], statements)
|
64
64
|
|
65
|
-
|
65
|
+
assert_raises(ArgumentError) do
|
66
66
|
ARBC.set_role('foo', :duration => :nonsense)
|
67
67
|
end
|
68
68
|
end
|
@@ -141,4 +141,56 @@ class AdapterExtensionTests < Test::Unit::TestCase
|
|
141
141
|
%{ALTER TABLE "foo" ENABLE TRIGGER "baz";}
|
142
142
|
], statements)
|
143
143
|
end
|
144
|
+
|
145
|
+
def test_add_column_with_expression
|
146
|
+
Mig.add_column(:foo, :bar, :integer, :default => 100)
|
147
|
+
Mig.add_column(:foo, :bar, :integer, :default => {
|
148
|
+
:expression => '1 + 1'
|
149
|
+
})
|
150
|
+
|
151
|
+
Mig.add_column(:foo, :bar, :integer, :null => false, :default => {
|
152
|
+
:expression => '1 + 1'
|
153
|
+
})
|
154
|
+
|
155
|
+
if RUBY_PLATFORM == 'java' || ActiveRecord::VERSION::MAJOR <= 2
|
156
|
+
assert_equal([
|
157
|
+
%{ALTER TABLE "foo" ADD COLUMN "bar" integer},
|
158
|
+
%{ALTER TABLE "foo" ALTER COLUMN "bar" SET DEFAULT 100},
|
159
|
+
%{ALTER TABLE "foo" ADD COLUMN "bar" integer},
|
160
|
+
%{ALTER TABLE "foo" ALTER COLUMN "bar" SET DEFAULT 1 + 1;},
|
161
|
+
%{ALTER TABLE "foo" ADD COLUMN "bar" integer},
|
162
|
+
%{ALTER TABLE "foo" ALTER COLUMN "bar" SET DEFAULT 1 + 1;},
|
163
|
+
%{UPDATE "foo" SET "bar" = 1 + 1 WHERE "bar" IS NULL},
|
164
|
+
%{ALTER TABLE "foo" ALTER "bar" SET NOT NULL},
|
165
|
+
], statements)
|
166
|
+
else
|
167
|
+
assert_equal([
|
168
|
+
%{ALTER TABLE "foo" ADD COLUMN "bar" integer DEFAULT 100},
|
169
|
+
%{ALTER TABLE "foo" ADD COLUMN "bar" integer DEFAULT 1 + 1},
|
170
|
+
%{ALTER TABLE "foo" ADD COLUMN "bar" integer DEFAULT 1 + 1 NOT NULL}
|
171
|
+
], statements)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_change_column_with_expression
|
176
|
+
Mig.change_column(:foo, :bar, :integer, :default => 100)
|
177
|
+
Mig.change_column(:foo, :bar, :integer, :default => {
|
178
|
+
:expression => '1 + 1'
|
179
|
+
})
|
180
|
+
|
181
|
+
Mig.change_column(:foo, :bar, :integer, :null => false, :default => {
|
182
|
+
:expression => '1 + 1'
|
183
|
+
})
|
184
|
+
|
185
|
+
assert_equal([
|
186
|
+
%{ALTER TABLE "foo" ALTER COLUMN "bar" TYPE integer},
|
187
|
+
%{ALTER TABLE "foo" ALTER COLUMN "bar" SET DEFAULT 100},
|
188
|
+
%{ALTER TABLE "foo" ALTER COLUMN "bar" TYPE integer},
|
189
|
+
%{ALTER TABLE "foo" ALTER COLUMN "bar" SET DEFAULT 1 + 1;},
|
190
|
+
%{ALTER TABLE "foo" ALTER COLUMN "bar" TYPE integer},
|
191
|
+
%{ALTER TABLE "foo" ALTER COLUMN "bar" SET DEFAULT 1 + 1;},
|
192
|
+
%{UPDATE "foo" SET "bar" = 1 + 1 WHERE "bar" IS NULL},
|
193
|
+
%{ALTER TABLE "foo" ALTER "bar" SET NOT NULL},
|
194
|
+
], statements)
|
195
|
+
end
|
144
196
|
end
|