activerecord-postgresql-extensions 0.1.0 → 0.2.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.
- 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
|