activerecord-postgresql-extensions 0.0.12 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/Gemfile +3 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +7 -2
- data/Rakefile +4 -17
- data/activerecord-postgresql-extensions.gemspec +13 -57
- data/lib/{postgresql_extensions/postgresql_adapter_extensions.rb → active_record/postgresql_extensions/adapter_extensions.rb} +44 -46
- data/lib/{postgresql_extensions/postgresql_constraints.rb → active_record/postgresql_extensions/constraints.rb} +121 -10
- data/lib/{postgresql_extensions/postgresql_extensions.rb → active_record/postgresql_extensions/extensions.rb} +1 -1
- data/lib/{postgresql_extensions → active_record/postgresql_extensions}/foreign_key_associations.rb +9 -1
- data/lib/{postgresql_extensions/postgresql_functions.rb → active_record/postgresql_extensions/functions.rb} +9 -3
- data/lib/{postgresql_extensions/postgresql_geometry.rb → active_record/postgresql_extensions/geometry.rb} +111 -35
- data/lib/{postgresql_extensions/postgresql_indexes.rb → active_record/postgresql_extensions/indexes.rb} +4 -2
- data/lib/{postgresql_extensions/postgresql_languages.rb → active_record/postgresql_extensions/languages.rb} +1 -1
- data/lib/{postgresql_extensions/postgresql_permissions.rb → active_record/postgresql_extensions/permissions.rb} +3 -3
- data/lib/active_record/postgresql_extensions/postgis.rb +53 -0
- data/lib/{postgresql_extensions/postgresql_roles.rb → active_record/postgresql_extensions/roles.rb} +1 -1
- data/lib/{postgresql_extensions/postgresql_rules.rb → active_record/postgresql_extensions/rules.rb} +3 -3
- data/lib/{postgresql_extensions/postgresql_schemas.rb → active_record/postgresql_extensions/schemas.rb} +1 -1
- data/lib/{postgresql_extensions/postgresql_sequences.rb → active_record/postgresql_extensions/sequences.rb} +2 -2
- data/lib/{postgresql_extensions/postgresql_tables.rb → active_record/postgresql_extensions/tables.rb} +18 -4
- data/lib/{postgresql_extensions/postgresql_tablespaces.rb → active_record/postgresql_extensions/tablespaces.rb} +1 -1
- data/lib/{postgresql_extensions/postgresql_text_search.rb → active_record/postgresql_extensions/text_search.rb} +3 -3
- data/lib/{postgresql_extensions/postgresql_triggers.rb → active_record/postgresql_extensions/triggers.rb} +1 -1
- data/lib/{postgresql_extensions/postgresql_types.rb → active_record/postgresql_extensions/types.rb} +1 -1
- data/lib/active_record/postgresql_extensions/utils.rb +23 -0
- data/lib/active_record/postgresql_extensions/version.rb +7 -0
- data/lib/{postgresql_extensions/postgresql_views.rb → active_record/postgresql_extensions/views.rb} +2 -2
- data/lib/activerecord-postgresql-extensions.rb +23 -22
- data/test/adapter_tests.rb +9 -9
- data/test/constraints_tests.rb +155 -0
- data/test/database.yml +17 -0
- data/test/geometry_tests.rb +224 -52
- data/test/index_tests.rb +16 -1
- data/test/rules_tests.rb +4 -4
- data/test/sequences_tests.rb +0 -22
- data/test/tables_tests.rb +28 -31
- data/test/test_helper.rb +70 -23
- data/test/trigger_tests.rb +5 -5
- metadata +112 -25
- data/VERSION +0 -1
data/.gitignore
ADDED
data/Gemfile
ADDED
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -12,7 +12,7 @@ PostgreSQL adapter including:
|
|
12
12
|
functions, sequences, views, schemas and triggers.
|
13
13
|
|
14
14
|
* better support for creating indexes with expressions so you can use functions
|
15
|
-
and
|
15
|
+
and GiST and GIN indexes.
|
16
16
|
|
17
17
|
* support for manipulating role privileges.
|
18
18
|
|
@@ -20,10 +20,15 @@ PostgreSQL adapter including:
|
|
20
20
|
creating tables.
|
21
21
|
|
22
22
|
* support for automatically detecting foreign key relationships and building
|
23
|
-
ActiveRecord associations accordingly. This associations can be
|
23
|
+
ActiveRecord associations accordingly. This associations can be overridden
|
24
24
|
as necessary and are sane enough that they won't try to overwrite existing
|
25
25
|
associations.
|
26
26
|
|
27
|
+
* support for some PostGIS functionality including some support for using
|
28
|
+
PostGIS columns in migrations. For manipulating PostGIS data, see our
|
29
|
+
geos-extensions gem at https://github.com/zoocasa/geos-extensions or
|
30
|
+
the RGeo project at https://github.com/dazuma/rgeo .
|
31
|
+
|
27
32
|
== First Public Release Notice!
|
28
33
|
|
29
34
|
This is the first public release of this gem, so while it has been kind to us
|
data/Rakefile
CHANGED
@@ -8,6 +8,7 @@ gem 'rdoc', '~> 3.12'
|
|
8
8
|
require 'rubygems/package_task'
|
9
9
|
require 'rake/testtask'
|
10
10
|
require 'rdoc/task'
|
11
|
+
require 'bundler/gem_tasks'
|
11
12
|
|
12
13
|
if RUBY_VERSION >= '1.9'
|
13
14
|
begin
|
@@ -19,27 +20,13 @@ end
|
|
19
20
|
|
20
21
|
$:.push 'lib'
|
21
22
|
|
22
|
-
version =
|
23
|
-
|
24
|
-
begin
|
25
|
-
require 'jeweler'
|
26
|
-
Jeweler::Tasks.new do |gem|
|
27
|
-
gem.name = "activerecord-postgresql-extensions"
|
28
|
-
gem.summary = "A whole bunch of extensions the ActiveRecord PostgreSQL adapter."
|
29
|
-
gem.description = gem.summary
|
30
|
-
gem.email = "code@zoocasa.com"
|
31
|
-
gem.homepage = "http://github.com/zoocasa/activerecord-postgresql-extensions"
|
32
|
-
gem.authors = [ "J Smith" ]
|
33
|
-
end
|
34
|
-
Jeweler::GemcutterTasks.new
|
35
|
-
rescue LoadError
|
36
|
-
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
37
|
-
end
|
23
|
+
version = ActiveRecord::PostgreSQLExtensions::VERSION
|
38
24
|
|
39
25
|
desc 'Test PostgreSQL extensions'
|
40
26
|
Rake::TestTask.new(:test) do |t|
|
41
27
|
t.test_files = FileList['test/**/*_tests.rb']
|
42
|
-
t.verbose =
|
28
|
+
t.verbose = !!ENV['VERBOSE_TESTS']
|
29
|
+
t.warning = !!ENV['WARNINGS']
|
43
30
|
end
|
44
31
|
|
45
32
|
desc 'Build docs'
|
@@ -1,76 +1,32 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
1
|
# -*- encoding: utf-8 -*-
|
5
2
|
|
3
|
+
require File.expand_path('../lib/active_record/postgresql_extensions/version', __FILE__)
|
4
|
+
|
6
5
|
Gem::Specification.new do |s|
|
7
6
|
s.name = "activerecord-postgresql-extensions"
|
8
|
-
s.version =
|
7
|
+
s.version = ActiveRecord::PostgreSQLExtensions::VERSION
|
9
8
|
|
10
9
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
10
|
s.authors = ["J Smith"]
|
12
|
-
s.date = "2012-03-22"
|
13
11
|
s.description = "A whole bunch of extensions the ActiveRecord PostgreSQL adapter."
|
12
|
+
s.summary = s.description
|
14
13
|
s.email = "code@zoocasa.com"
|
15
14
|
s.extra_rdoc_files = [
|
16
15
|
"README.rdoc"
|
17
16
|
]
|
18
|
-
s.files =
|
19
|
-
|
20
|
-
|
21
|
-
"Rakefile",
|
22
|
-
"VERSION",
|
23
|
-
"activerecord-postgresql-extensions.gemspec",
|
24
|
-
"lib/activerecord-postgresql-extensions.rb",
|
25
|
-
"lib/postgresql_extensions/foreign_key_associations.rb",
|
26
|
-
"lib/postgresql_extensions/postgresql_adapter_extensions.rb",
|
27
|
-
"lib/postgresql_extensions/postgresql_constraints.rb",
|
28
|
-
"lib/postgresql_extensions/postgresql_extensions.rb",
|
29
|
-
"lib/postgresql_extensions/postgresql_functions.rb",
|
30
|
-
"lib/postgresql_extensions/postgresql_geometry.rb",
|
31
|
-
"lib/postgresql_extensions/postgresql_indexes.rb",
|
32
|
-
"lib/postgresql_extensions/postgresql_languages.rb",
|
33
|
-
"lib/postgresql_extensions/postgresql_permissions.rb",
|
34
|
-
"lib/postgresql_extensions/postgresql_roles.rb",
|
35
|
-
"lib/postgresql_extensions/postgresql_rules.rb",
|
36
|
-
"lib/postgresql_extensions/postgresql_schemas.rb",
|
37
|
-
"lib/postgresql_extensions/postgresql_sequences.rb",
|
38
|
-
"lib/postgresql_extensions/postgresql_tables.rb",
|
39
|
-
"lib/postgresql_extensions/postgresql_tablespaces.rb",
|
40
|
-
"lib/postgresql_extensions/postgresql_text_search.rb",
|
41
|
-
"lib/postgresql_extensions/postgresql_triggers.rb",
|
42
|
-
"lib/postgresql_extensions/postgresql_types.rb",
|
43
|
-
"lib/postgresql_extensions/postgresql_views.rb",
|
44
|
-
"test/adapter_tests.rb",
|
45
|
-
"test/constraints_tests.rb",
|
46
|
-
"test/extensions_tests.rb",
|
47
|
-
"test/functions_tests.rb",
|
48
|
-
"test/geometry_tests.rb",
|
49
|
-
"test/index_tests.rb",
|
50
|
-
"test/languages_tests.rb",
|
51
|
-
"test/permissions_tests.rb",
|
52
|
-
"test/roles_tests.rb",
|
53
|
-
"test/rules_tests.rb",
|
54
|
-
"test/schemas_tests.rb",
|
55
|
-
"test/sequences_tests.rb",
|
56
|
-
"test/tables_tests.rb",
|
57
|
-
"test/tablespace_tests.rb",
|
58
|
-
"test/test_helper.rb",
|
59
|
-
"test/text_search_tests.rb",
|
60
|
-
"test/trigger_tests.rb"
|
61
|
-
]
|
17
|
+
s.files = `git ls-files`.split($\)
|
18
|
+
s.executables = s.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
19
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
62
20
|
s.homepage = "http://github.com/zoocasa/activerecord-postgresql-extensions"
|
63
21
|
s.require_paths = ["lib"]
|
64
|
-
s.rubygems_version = "1.8.15"
|
65
|
-
s.summary = "A whole bunch of extensions the ActiveRecord PostgreSQL adapter."
|
66
|
-
|
67
|
-
if s.respond_to? :specification_version then
|
68
|
-
s.specification_version = 3
|
69
22
|
|
70
|
-
|
71
|
-
|
72
|
-
|
23
|
+
s.add_dependency("activerecord", [">= 2.3"])
|
24
|
+
if RUBY_PLATFORM == "java"
|
25
|
+
s.add_dependency("activerecord-jdbcpostgresql-adapter")
|
73
26
|
else
|
27
|
+
s.add_dependency("pg")
|
74
28
|
end
|
29
|
+
s.add_dependency("rdoc")
|
30
|
+
s.add_dependency("rake", ["~> 0.9"])
|
75
31
|
end
|
76
32
|
|
@@ -1,12 +1,13 @@
|
|
1
1
|
|
2
2
|
module ActiveRecord
|
3
3
|
module ConnectionAdapters
|
4
|
-
class PostgreSQLAdapter
|
4
|
+
class PostgreSQLAdapter
|
5
5
|
if defined?(Rails)
|
6
6
|
LOGGER_REGEXP = /^#{Rails.root}(?!\/vendor\/rails)/
|
7
7
|
|
8
|
-
def query_with_extra_logging(
|
8
|
+
def query_with_extra_logging(*args) #:nodoc:
|
9
9
|
if ActiveRecord::Base.enable_extended_logging && Rails.logger && Rails.logger.level == Logger::DEBUG
|
10
|
+
sql = args.first
|
10
11
|
unless (sql =~ /(pg_get_constraintdef|pg_attribute|pg_class)/)
|
11
12
|
Rails.logger.debug
|
12
13
|
Rails.logger.debug(caller.select { |x|
|
@@ -14,12 +15,13 @@ module ActiveRecord
|
|
14
15
|
}.join("\n"))
|
15
16
|
end
|
16
17
|
end
|
17
|
-
query_without_extra_logging(
|
18
|
+
query_without_extra_logging(*args)
|
18
19
|
end
|
19
20
|
alias_method_chain :query, :extra_logging
|
20
21
|
|
21
|
-
def execute_with_extra_logging(
|
22
|
+
def execute_with_extra_logging(*args) #:nodoc:
|
22
23
|
if ActiveRecord::Base.enable_extended_logging && Rails.logger && Rails.logger.level == Logger::DEBUG
|
24
|
+
sql = args.first
|
23
25
|
unless (sql =~ /(pg_get_constraintdef|pg_attribute|pg_class)/)
|
24
26
|
Rails.logger.debug
|
25
27
|
Rails.logger.debug(caller.select { |x|
|
@@ -27,29 +29,11 @@ module ActiveRecord
|
|
27
29
|
}.join("\n"))
|
28
30
|
end
|
29
31
|
end
|
30
|
-
execute_without_extra_logging(
|
32
|
+
execute_without_extra_logging(*args)
|
31
33
|
end
|
32
34
|
alias_method_chain :execute, :extra_logging
|
33
35
|
end
|
34
36
|
|
35
|
-
# There seems to be a bug in ActiveRecord where it isn't setting
|
36
|
-
# the schema search path properly because it's using ',' as a
|
37
|
-
# separator rather than /,\s+/.
|
38
|
-
def schema_search_path_with_fix_csv=(schema_csv)
|
39
|
-
if schema_csv
|
40
|
-
csv = schema_csv.gsub(/,\s+/, ',')
|
41
|
-
execute "SET search_path TO #{csv}"
|
42
|
-
@schema_search_path = csv
|
43
|
-
end
|
44
|
-
end
|
45
|
-
alias_method_chain :schema_search_path=, :fix_csv
|
46
|
-
|
47
|
-
# Fix ActiveRecord bug when grabbing the current search_path.
|
48
|
-
def schema_search_path_with_fix_csv
|
49
|
-
@schema_search_path ||= query('SHOW search_path')[0][0].gsub(/,\s+/, ',')
|
50
|
-
end
|
51
|
-
alias_method_chain :schema_search_path, :fix_csv
|
52
|
-
|
53
37
|
# with_schema is kind of like with_scope. It wraps various
|
54
38
|
# object names in SQL statements into a PostgreSQL schema. You
|
55
39
|
# can have multiple with_schemas wrapped around each other, and
|
@@ -82,7 +66,7 @@ module ActiveRecord
|
|
82
66
|
#
|
83
67
|
# with_schema :geospatial do
|
84
68
|
# create_table(:test) do |t|
|
85
|
-
#
|
69
|
+
# ignore_scoped_schema do
|
86
70
|
# t.integer(
|
87
71
|
# :ref_id,
|
88
72
|
# :references => {
|
@@ -106,11 +90,11 @@ module ActiveRecord
|
|
106
90
|
# Here we see that we used the geospatial schema when naming the
|
107
91
|
# test table and dropped back to not specifying a schema when
|
108
92
|
# setting up the foreign key to the refs table. If we had not
|
109
|
-
# used
|
93
|
+
# used ignore_scoped_schema, the foreign key would have been defined
|
110
94
|
# thusly:
|
111
95
|
#
|
112
96
|
# FOREIGN KEY ("ref_id") REFERENCES "geospatial"."refs" ("id")
|
113
|
-
def
|
97
|
+
def ignore_scoped_schema
|
114
98
|
with_schema nil do
|
115
99
|
yield
|
116
100
|
end
|
@@ -124,18 +108,24 @@ module ActiveRecord
|
|
124
108
|
end
|
125
109
|
|
126
110
|
# Get the current scoped schema.
|
127
|
-
def
|
111
|
+
def current_scoped_schema
|
128
112
|
scoped_schemas.last
|
129
113
|
end
|
130
114
|
|
131
115
|
# A generic quoting method for PostgreSQL.
|
132
|
-
|
133
|
-
|
116
|
+
if RUBY_PLATFORM == 'java'
|
117
|
+
def quote_generic(g)
|
118
|
+
quote_column_name(g)
|
119
|
+
end
|
120
|
+
else
|
121
|
+
def quote_generic(g)
|
122
|
+
PGconn.quote_ident(g.to_s)
|
123
|
+
end
|
134
124
|
end
|
135
125
|
|
136
126
|
# A generic quoting method for PostgreSQL that specifically ignores
|
137
127
|
# any and all schemas.
|
138
|
-
def
|
128
|
+
def quote_generic_ignore_scoped_schema(g)
|
139
129
|
if g.is_a?(Hash)
|
140
130
|
quote_generic g.values.first
|
141
131
|
else
|
@@ -149,8 +139,8 @@ module ActiveRecord
|
|
149
139
|
if g.is_a?(Hash)
|
150
140
|
"#{quote_schema(g.keys.first)}.#{quote_generic(g.values.first)}"
|
151
141
|
else
|
152
|
-
if
|
153
|
-
quote_schema(
|
142
|
+
if current_scoped_schema
|
143
|
+
quote_schema(current_scoped_schema) << '.'
|
154
144
|
end.to_s << quote_generic(g)
|
155
145
|
end
|
156
146
|
end
|
@@ -215,13 +205,13 @@ module ActiveRecord
|
|
215
205
|
# # => "geospatial"."epois"
|
216
206
|
#
|
217
207
|
# with_schema(:geospatial) do
|
218
|
-
#
|
208
|
+
# ignore_scoped_schema do
|
219
209
|
# quote_table_name(:epois)
|
220
210
|
# end
|
221
211
|
# end
|
222
212
|
# # => "epois"
|
223
213
|
def quote_table_name_with_schemas(name)
|
224
|
-
if
|
214
|
+
if current_scoped_schema || name.is_a?(Hash)
|
225
215
|
quote_generic_with_schema(name)
|
226
216
|
else
|
227
217
|
quote_table_name_without_schemas(name)
|
@@ -472,15 +462,21 @@ module ActiveRecord
|
|
472
462
|
end
|
473
463
|
alias_method_chain :tables, :views
|
474
464
|
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
465
|
+
unless RUBY_PLATFORM == "java"
|
466
|
+
# There seems to be a bug in ActiveRecord where it isn't setting
|
467
|
+
# the schema search path properly because it's using ',' as a
|
468
|
+
# separator rather than /,\s+/.
|
469
|
+
def schema_search_path_with_csv_fix=(schema_csv) #:nodoc:
|
470
|
+
self.schema_search_path_without_csv_fix = schema_csv.gsub(/,\s+/, ',') if schema_csv
|
471
|
+
end
|
472
|
+
alias_method_chain :schema_search_path=, :csv_fix
|
479
473
|
|
480
|
-
|
481
|
-
|
474
|
+
# Fix ActiveRecord bug when grabbing the current search_path.
|
475
|
+
def schema_search_path_with_csv_fix
|
476
|
+
@schema_search_path ||= query('SHOW search_path;')[0][0].gsub(/,\s+/, ',')
|
477
|
+
end
|
478
|
+
alias_method_chain :schema_search_path, :csv_fix
|
482
479
|
end
|
483
|
-
alias_method_chain :schema_search_path, :csv_fix
|
484
480
|
|
485
481
|
def disable_referential_integrity_with_views #:nodoc:
|
486
482
|
if supports_disable_referential_integrity? then
|
@@ -682,11 +678,13 @@ module ActiveRecord
|
|
682
678
|
alias_method_chain :change_column_default, :expression
|
683
679
|
end
|
684
680
|
|
685
|
-
class PostgreSQLColumn
|
681
|
+
class PostgreSQLColumn
|
686
682
|
def simplified_type_with_additional_types(field_type)
|
687
683
|
case field_type
|
688
684
|
when 'geometry'
|
689
685
|
:geometry
|
686
|
+
when 'geography'
|
687
|
+
:geography
|
690
688
|
when 'tsvector'
|
691
689
|
:tsvector
|
692
690
|
else
|
@@ -707,8 +705,8 @@ module ActiveRecord
|
|
707
705
|
}
|
708
706
|
end
|
709
707
|
|
710
|
-
def
|
711
|
-
self.connection.
|
708
|
+
def ignore_scoped_schema
|
709
|
+
self.connection.ignore_scoped_schema { |*block_args|
|
712
710
|
yield(*block_args)
|
713
711
|
}
|
714
712
|
end
|
@@ -717,8 +715,8 @@ module ActiveRecord
|
|
717
715
|
self.connection.scope_schemas
|
718
716
|
end
|
719
717
|
|
720
|
-
def
|
721
|
-
self.connection.
|
718
|
+
def current_scoped_schema
|
719
|
+
self.connection.current_scoped_schema
|
722
720
|
end
|
723
721
|
|
724
722
|
def sequence_exists?
|
@@ -1,4 +1,7 @@
|
|
1
1
|
|
2
|
+
require 'active_record/connection_adapters/postgresql_adapter'
|
3
|
+
require 'active_record/postgresql_extensions/utils'
|
4
|
+
|
2
5
|
module ActiveRecord
|
3
6
|
class InvalidForeignKeyAction < ActiveRecordError #:nodoc:
|
4
7
|
def initialize(action)
|
@@ -25,7 +28,7 @@ module ActiveRecord
|
|
25
28
|
end
|
26
29
|
|
27
30
|
module ConnectionAdapters
|
28
|
-
class PostgreSQLAdapter
|
31
|
+
class PostgreSQLAdapter
|
29
32
|
# Adds a CHECK constraint to the table. See
|
30
33
|
# PostgreSQLCheckConstraint for usage.
|
31
34
|
def add_check_constraint(table, expression, options = {})
|
@@ -50,8 +53,16 @@ module ActiveRecord
|
|
50
53
|
execute("#{sql};")
|
51
54
|
end
|
52
55
|
|
56
|
+
# Adds an EXCLUDE constraint to the table. See
|
57
|
+
# PostgreSQLExcludeConstraint for details.
|
58
|
+
def add_exclude_constraint(table, excludes, options = {})
|
59
|
+
sql = "ALTER TABLE #{quote_table_name(table)} ADD "
|
60
|
+
sql << PostgreSQLExcludeConstraint.new(self, table, excludes, options).to_s
|
61
|
+
execute("#{sql};")
|
62
|
+
end
|
63
|
+
|
53
64
|
# Drops a constraint from the table. Use this to drop CHECK,
|
54
|
-
# UNIQUE and FOREIGN KEY constraints from a table.
|
65
|
+
# UNIQUE, EXCLUDE and FOREIGN KEY constraints from a table.
|
55
66
|
#
|
56
67
|
# Options:
|
57
68
|
#
|
@@ -304,7 +315,7 @@ module ActiveRecord
|
|
304
315
|
# PostgreSQLAdapter#create_index method similarly. The create_index
|
305
316
|
# method adds a couple of PostgreSQL-specific options if you need them.
|
306
317
|
#
|
307
|
-
# ==== Examples
|
318
|
+
# ==== Examples
|
308
319
|
#
|
309
320
|
# # using the constraint method:
|
310
321
|
# add_unique_constraint(:foo, [ :fancy_id, :another_fancy_id ])
|
@@ -335,7 +346,8 @@ module ActiveRecord
|
|
335
346
|
# couple of additional parameters to indexes to govern disk usage and
|
336
347
|
# such. This option is a simple String that lets you insert these
|
337
348
|
# options as necessary. See the PostgreSQL documentation on index
|
338
|
-
# storage parameters for details.
|
349
|
+
# storage parameters for details. <tt>:index_parameters</tt> can also
|
350
|
+
# be used.
|
339
351
|
# * <tt>:tablespace</tt> - allows you to specify a tablespace for the
|
340
352
|
# unique index being created. See the PostgreSQL documentation on
|
341
353
|
# tablespaces for details.
|
@@ -363,7 +375,7 @@ module ActiveRecord
|
|
363
375
|
sql = "#{constraint_name}UNIQUE ("
|
364
376
|
sql << Array(columns).collect { |c| base.quote_column_name(c) }.join(', ')
|
365
377
|
sql << ")"
|
366
|
-
sql << " WITH (#{options[:storage_parameters]})" if options[:storage_parameters]
|
378
|
+
sql << " WITH (#{options[:storage_parameters] || options[:index_parameters]})" if options[:storage_parameters] || options[:index_parameters]
|
367
379
|
sql << " USING INDEX TABLESPACE #{base.quote_tablespace(options[:tablespace])}" if options[:tablespace]
|
368
380
|
sql
|
369
381
|
end
|
@@ -470,13 +482,13 @@ module ActiveRecord
|
|
470
482
|
# You can also create new FOREIGN KEY constraints outside of a table
|
471
483
|
# definition using PostgreSQLAdapter#add_foreign_key.
|
472
484
|
#
|
473
|
-
# ==== Examples
|
485
|
+
# ==== Examples
|
474
486
|
#
|
475
487
|
# add_foreign_key(:foo, :bar_id, :bar)
|
476
|
-
# # => ALTER TABLE "
|
488
|
+
# # => ALTER TABLE "foo" ADD FOREIGN KEY ("bar_id") REFERENCES "bar";
|
477
489
|
#
|
478
490
|
# add_foreign_key(:foo, :bar_id, :bar, :id)
|
479
|
-
# # => ALTER TABLE "
|
491
|
+
# # => ALTER TABLE "foo" ADD FOREIGN KEY ("bar_id") REFERENCES "bar"("id");
|
480
492
|
#
|
481
493
|
# add_foreign_key(:foo, [ :bar_id, :blort_id ], :bar, [ :id, :blort_id ],
|
482
494
|
# :name => 'my_fk', :match => :simple
|
@@ -505,7 +517,7 @@ module ActiveRecord
|
|
505
517
|
# the <tt>:deferrable</tt>, <tt>:match</tt>, <tt>:on_delete</tt>
|
506
518
|
# and <tt>:on_update</tt> options.
|
507
519
|
#
|
508
|
-
# === Dropping
|
520
|
+
# === Dropping FOREIGN KEY Constraints
|
509
521
|
#
|
510
522
|
# Like all PostgreSQL constraints, you can use
|
511
523
|
# PostgreSQLAdapter#drop_constraint to remove a constraint from a
|
@@ -522,7 +534,7 @@ module ActiveRecord
|
|
522
534
|
assert_valid_action(options[:on_update]) if options[:on_update]
|
523
535
|
assert_valid_deferrable_option(options[:deferrable])
|
524
536
|
@columns, @ref_table, @ref_columns = columns, ref_table, ref_columns
|
525
|
-
@schema = base.
|
537
|
+
@schema = base.current_scoped_schema
|
526
538
|
super(base, options)
|
527
539
|
end
|
528
540
|
|
@@ -564,5 +576,104 @@ module ActiveRecord
|
|
564
576
|
end
|
565
577
|
end
|
566
578
|
end
|
579
|
+
|
580
|
+
# Creates EXCLUDE constraints for PostgreSQL tables and columns.
|
581
|
+
#
|
582
|
+
# This class is meant to be used by PostgreSQL column and table
|
583
|
+
# definition and manipulation methods. There are two ways to create
|
584
|
+
# a EXCLUDE constraint:
|
585
|
+
#
|
586
|
+
# * on a table definition
|
587
|
+
# * when altering a table
|
588
|
+
#
|
589
|
+
# In both cases, a Hash or an Array of Hashes should be used to set the
|
590
|
+
# EXCLUDE constraint checks. The Hash(es) should be in the format
|
591
|
+
# <tt>{ :element => ..., :with => ... }</tt>, where <tt>:element</tt> is
|
592
|
+
# a column name or expression and <tt>:with</tt> is the operator to
|
593
|
+
# compare against. The key <tt>:operator</tt> is an alias for <tt>:where</tt>.
|
594
|
+
#
|
595
|
+
# === Table Definition
|
596
|
+
#
|
597
|
+
# EXCLUDE constraints can also be applied to the table directly
|
598
|
+
# rather than on a column definition.
|
599
|
+
#
|
600
|
+
# ==== Example:
|
601
|
+
#
|
602
|
+
# The following example produces the same result as above:
|
603
|
+
#
|
604
|
+
# create_table('foo') do |t|
|
605
|
+
# t.integer :blort
|
606
|
+
# t.exclude({
|
607
|
+
# :element => 'length(blort)',
|
608
|
+
# :with => '='
|
609
|
+
# }, {
|
610
|
+
# :name => 'exclude_blort_length'
|
611
|
+
# })
|
612
|
+
# end
|
613
|
+
#
|
614
|
+
# # Produces:
|
615
|
+
# #
|
616
|
+
# # CREATE TABLE "foo" (
|
617
|
+
# # "id" serial primary key,
|
618
|
+
# # "blort" text,
|
619
|
+
# # CONSTRAINT "exclude_blort_length" EXCLUDE (length(blort) WITH =)
|
620
|
+
# # );
|
621
|
+
#
|
622
|
+
# === Table Manipulation
|
623
|
+
#
|
624
|
+
# You can also create new EXCLUDE constraints outside of a table
|
625
|
+
# definition using PostgreSQLAdapter#add_exclude_constraint.
|
626
|
+
#
|
627
|
+
# ==== Examples
|
628
|
+
#
|
629
|
+
# add_exclude_constraint(:foo, { :element => :bar_id, :with => '=' })
|
630
|
+
# # => ALTER TABLE "foo" ADD EXCLUDE ("bar_id" WITH =);
|
631
|
+
#
|
632
|
+
# === Options for EXCLUDE Constraints
|
633
|
+
#
|
634
|
+
# * <tt>:using</tt> - sets the index type to be used. Usually this will
|
635
|
+
# <tt>:gist</tt>, but the default is left blank to allow for the PostgreSQL
|
636
|
+
# default which is <tt>:btree</tt>. See the PostgreSQL docs for details.
|
637
|
+
# * <tt>:storage_parameters</tt> - PostgreSQL allows you to add a
|
638
|
+
# couple of additional parameters to indexes to govern disk usage and
|
639
|
+
# such. This option is a simple String that lets you insert these
|
640
|
+
# options as necessary. See the PostgreSQL documentation on index
|
641
|
+
# storage parameters for details. <tt>:index_parameters</tt> can also
|
642
|
+
# be used.
|
643
|
+
# * <tt>:tablespace</tt> - allows you to specify a tablespace for the
|
644
|
+
# index being created. See the PostgreSQL documentation on
|
645
|
+
# tablespaces for details.
|
646
|
+
# * <tt>:conditions</tt> - sets the WHERE conditions for the EXCLUDE
|
647
|
+
# constraint. You can also use the <tt>:where</tt> option.
|
648
|
+
#
|
649
|
+
# === Dropping EXCLUDE Constraints
|
650
|
+
#
|
651
|
+
# Like all PostgreSQL constraints, you can use
|
652
|
+
# PostgreSQLAdapter#drop_constraint to remove a constraint from a
|
653
|
+
# table.
|
654
|
+
class PostgreSQLExcludeConstraint < PostgreSQLConstraint
|
655
|
+
attr_accessor :excludes
|
656
|
+
|
657
|
+
def initialize(base, table, excludes, options = {}) #:nodoc:
|
658
|
+
@excludes = ActiveRecord::PostgreSQLExtensions::Utils.hash_or_array_of_hashes(excludes)
|
659
|
+
|
660
|
+
super(base, options)
|
661
|
+
end
|
662
|
+
|
663
|
+
def to_sql #:nodoc:
|
664
|
+
sql = String.new
|
665
|
+
sql << "#{constraint_name}EXCLUDE "
|
666
|
+
sql << "USING #{base.quote_column_name(options[:using])} " if options[:using]
|
667
|
+
sql << "(" << excludes.collect { |e|
|
668
|
+
"#{e[:element]} WITH #{e[:with] || e[:operator]}"
|
669
|
+
}.join(', ')
|
670
|
+
sql << ")"
|
671
|
+
sql << " WITH (#{options[:index_parameters] || options[:storage_parameters]})" if options[:index_parameters] || options[:storage_parameters]
|
672
|
+
sql << " USING INDEX TABLESPACE #{base.quote_tablespace(options[:tablespace])}" if options[:tablespace]
|
673
|
+
sql << " WHERE (#{options[:conditions] || options[:where]})" if options[:conditions] || options[:where]
|
674
|
+
sql
|
675
|
+
end
|
676
|
+
alias :to_s :to_sql
|
677
|
+
end
|
567
678
|
end
|
568
679
|
end
|