activerecord-postgis-adapter 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.rdoc +9 -0
- data/README.rdoc +4 -2
- data/Version +1 -1
- data/lib/active_record/connection_adapters/postgis_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/postgis_adapter/databases.rake +93 -58
- data/lib/active_record/connection_adapters/postgis_adapter/jdbc_connection.rb +27 -18
- data/lib/active_record/connection_adapters/postgis_adapter/main_adapter.rb +5 -2
- data/lib/active_record/connection_adapters/postgis_adapter/pg_connection.rb +0 -1
- data/lib/active_record/connection_adapters/postgis_adapter/spatial_column.rb +5 -5
- data/lib/active_record/connection_adapters/postgis_adapter/spatial_table_definition.rb +6 -1
- metadata +3 -3
data/History.rdoc
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
=== 0.5.1 / 2013-02-04
|
2
|
+
|
3
|
+
* Database creation properly treats geometry_columns as a view when setting owner. (Pull request by hendrikstier)
|
4
|
+
* Provide rake db:gis:setup task. (Pull request by Cody Russell)
|
5
|
+
* Modifications for compatibility with postgres_ext. (Pull request by legendetm)
|
6
|
+
* SpatialTableDefinition properly subclasses the Postgres-specific table definition class, if available. (Pull request by Joe Noon)
|
7
|
+
* Database creation script no longer fails if the username includes weird characters. (Contributed by Toms Mikoss)
|
8
|
+
* Updates for compatibility with jdbc-postgres 9.2.1002.1
|
9
|
+
|
1
10
|
=== 0.5.0 / 2012-12-12
|
2
11
|
|
3
12
|
Thanks to the many who have submitted pull requests. A bunch of them are in this release. Special thanks to Nick Muerdter, who succeeded in porting the adapter to work with the JDBC Postgres adapter in JRuby, and also got Travis up and running for the project.
|
data/README.rdoc
CHANGED
@@ -128,7 +128,8 @@ system; you shouldn't try to run such a query against a lat/long
|
|
128
128
|
|
129
129
|
This adapter has the following requirements:
|
130
130
|
|
131
|
-
* Ruby 1.8.7 or later. Ruby 1.9.2 or later preferred. JRuby 1.6.3 or
|
131
|
+
* Ruby 1.8.7 or later. Ruby 1.9.2 or later preferred. JRuby 1.6.3 or
|
132
|
+
later also supported.
|
132
133
|
* PostgreSQL 9.0 or later.
|
133
134
|
* PostGIS 1.5, PostGIS 2.0, or later.
|
134
135
|
* \ActiveRecord 3.0.3 or later. Earlier versions will not work.
|
@@ -136,7 +137,8 @@ This adapter has the following requirements:
|
|
136
137
|
* rgeo gem 0.3.20 or later.
|
137
138
|
* rgeo-activerecord gem 0.4.6 or later.
|
138
139
|
|
139
|
-
Please note that this version of the adapter is targeted towards Rails
|
140
|
+
Please note that this version of the adapter is targeted towards Rails
|
141
|
+
3.x only. The upcoming version 0.6 will target Rails 4.0.
|
140
142
|
|
141
143
|
Install this adapter as a gem:
|
142
144
|
|
data/Version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.1
|
@@ -43,14 +43,102 @@ class Object
|
|
43
43
|
end
|
44
44
|
|
45
45
|
|
46
|
+
namespace :db do
|
47
|
+
namespace :gis do
|
48
|
+
desc "Setup PostGIS data in the database"
|
49
|
+
task :setup => [:load_config, :rails_env] do
|
50
|
+
configs_for_environment.each { |config| setup_gis(config) }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
# superuser name/password
|
57
|
+
def get_su_auth(config_)
|
58
|
+
username_ = config_['username']
|
59
|
+
su_username_ = config_['su_username'] || username_
|
60
|
+
su_password_ = config_['su_password'] || config_['password']
|
61
|
+
has_su_ = config_.include?('su_username')
|
62
|
+
|
63
|
+
[username_, su_username_, su_password_, has_su_]
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def get_search_path(config_)
|
68
|
+
config_["schema_search_path"].to_s.strip.split(',').map(&:strip)
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
# Install postgis definitions into the database.
|
73
|
+
# Note: a superuser is required to run the postgis definitions.
|
74
|
+
# If a separate superuser is provided, we need to grant privileges on
|
75
|
+
# the postgis definitions over to the regular user afterwards.
|
76
|
+
# We also need to set the ownership of the postgis tables (spatial_ref_sys
|
77
|
+
# and geometry_columns) to the regular user. This is required to e.g.
|
78
|
+
# be able to disable referential integrity on the database when using
|
79
|
+
# a database cleaner truncation strategy during testing.
|
80
|
+
# The schema for the postgis definitions is chosen as follows:
|
81
|
+
# If "postgis" is present in the search path, use it.
|
82
|
+
# Otherwise, use the last schema in the search path.
|
83
|
+
# If no search path is given, use "public".
|
84
|
+
def setup_gis(config_)
|
85
|
+
# Initial setup of the database: Add schemas from the search path.
|
86
|
+
# If a superuser is given, we log in as the superuser, but we make sure
|
87
|
+
# the schemas are owned by the regular user.
|
88
|
+
username_, su_username_, su_password_, has_su_ = get_su_auth(config_)
|
89
|
+
::ActiveRecord::Base.establish_connection(config_.merge('schema_search_path' => 'public', 'username' => su_username_, 'password' => su_password_))
|
90
|
+
conn_ = ::ActiveRecord::Base.connection
|
91
|
+
search_path_ = get_search_path(config_)
|
92
|
+
quoted_username_ = ::PGconn.quote_ident(username_)
|
93
|
+
auth_ = has_su_ ? " AUTHORIZATION #{quoted_username_}" : ''
|
94
|
+
search_path_.each do |schema_|
|
95
|
+
exists = schema_.downcase == 'public' || conn_.execute("SELECT 1 FROM pg_catalog.pg_namespace WHERE nspname='#{schema_}'").try(:first)
|
96
|
+
conn_.execute("CREATE SCHEMA #{schema_}#{auth_}") unless exists
|
97
|
+
end
|
98
|
+
|
99
|
+
script_dir_ = config_['script_dir']
|
100
|
+
postgis_extension_ = config_['postgis_extension']
|
101
|
+
if script_dir_ || postgis_extension_
|
102
|
+
postgis_schema_ = search_path_.include?('postgis') ? 'postgis' : (search_path_.last || 'public')
|
103
|
+
if script_dir_
|
104
|
+
# Use script_dir (for postgresql < 9.1 or postgis < 2.0)
|
105
|
+
conn_.execute("SET search_path TO #{postgis_schema_}")
|
106
|
+
conn_.execute(::File.read(::File.expand_path('postgis.sql', script_dir_)))
|
107
|
+
conn_.execute(::File.read(::File.expand_path('spatial_ref_sys.sql', script_dir_)))
|
108
|
+
elsif postgis_extension_
|
109
|
+
# Use postgis_extension (for postgresql >= 9.1 and postgis >= 2.0)
|
110
|
+
postgis_extension_ = 'postgis' if postgis_extension_ == true
|
111
|
+
postgis_extension_ = postgis_extension_.to_s.split(',') unless postgis_extension_.is_a?(::Array)
|
112
|
+
postgis_extension_.each do |extname_|
|
113
|
+
if extname_ == 'postgis_topology'
|
114
|
+
raise ArgumentError, "'topology' must be in schema_search_path for postgis_topology" unless search_path_.include?('topology')
|
115
|
+
conn_.execute("CREATE EXTENSION #{extname_} SCHEMA topology")
|
116
|
+
else
|
117
|
+
conn_.execute("CREATE EXTENSION #{extname_} SCHEMA #{postgis_schema_}")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
if has_su_
|
122
|
+
conn_.execute("GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA #{postgis_schema_} TO #{quoted_username_}")
|
123
|
+
conn_.execute("GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA #{postgis_schema_} TO #{quoted_username_}")
|
124
|
+
|
125
|
+
postgis_version = conn_.execute( "SELECT #{postgis_schema_}.postgis_version();" ).first[ 'postgis_version' ]
|
126
|
+
if postgis_version =~ /^2/
|
127
|
+
conn_.execute("ALTER VIEW #{postgis_schema_}.geometry_columns OWNER TO #{quoted_username_}")
|
128
|
+
else
|
129
|
+
conn_.execute("ALTER TABLE #{postgis_schema_}.geometry_columns OWNER TO #{quoted_username_}")
|
130
|
+
end
|
131
|
+
conn_.execute("ALTER TABLE #{postgis_schema_}.spatial_ref_sys OWNER TO #{quoted_username_}")
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
|
46
137
|
def create_database(config_)
|
47
138
|
if config_['adapter'] == 'postgis'
|
48
139
|
@encoding = config_['encoding'] || ::ENV['CHARSET'] || 'utf8'
|
49
140
|
begin
|
50
|
-
has_su_ = config_
|
51
|
-
username_ = config_['username'] # regular user name
|
52
|
-
su_username_ = config_['su_username'] || username_ # superuser name
|
53
|
-
su_password_ = config_['su_password'] || config_['password'] # superuser password
|
141
|
+
username_, su_username_, su_password_, has_su_ = get_su_auth(config_)
|
54
142
|
|
55
143
|
# Create the database. Optionally do so as the given superuser.
|
56
144
|
# But make sure the database is owned by the regular user.
|
@@ -59,60 +147,7 @@ def create_database(config_)
|
|
59
147
|
extra_configs_['owner'] = username_ if has_su_
|
60
148
|
::ActiveRecord::Base.connection.create_database(config_['database'], config_.merge(extra_configs_))
|
61
149
|
|
62
|
-
|
63
|
-
# If a superuser is given, we log in as the superuser, but we make sure
|
64
|
-
# the schemas are owned by the regular user.
|
65
|
-
::ActiveRecord::Base.establish_connection(config_.merge('schema_search_path' => 'public', 'username' => su_username_, 'password' => su_password_))
|
66
|
-
conn_ = ::ActiveRecord::Base.connection
|
67
|
-
search_path_ = config_["schema_search_path"].to_s.strip
|
68
|
-
search_path_ = search_path_.split(",").map{ |sp_| sp_.strip }
|
69
|
-
auth_ = has_su_ ? " AUTHORIZATION #{username_}" : ''
|
70
|
-
search_path_.each do |schema_|
|
71
|
-
exists = schema_.downcase == 'public' || conn_.execute("SELECT 1 FROM pg_catalog.pg_namespace WHERE nspname='#{schema_}'").try(:first)
|
72
|
-
conn_.execute("CREATE SCHEMA #{schema_}#{auth_}") unless exists
|
73
|
-
end
|
74
|
-
|
75
|
-
# Install postgis definitions into the database.
|
76
|
-
# Note: a superuser is required to run the postgis definitions.
|
77
|
-
# If a separate superuser is provided, we need to grant privileges on
|
78
|
-
# the postgis definitions over to the regular user afterwards.
|
79
|
-
# We also need to set the ownership of the postgis tables (spatial_ref_sys
|
80
|
-
# and geometry_columns) to the regular user. This is required to e.g.
|
81
|
-
# be able to disable referential integrity on the database when using
|
82
|
-
# a database cleaner truncation strategy during testing.
|
83
|
-
# The schema for the postgis definitions is chosen as follows:
|
84
|
-
# If "postgis" is present in the search path, use it.
|
85
|
-
# Otherwise, use the last schema in the search path.
|
86
|
-
# If no search path is given, use "public".
|
87
|
-
script_dir_ = config_['script_dir']
|
88
|
-
postgis_extension_ = config_['postgis_extension']
|
89
|
-
if script_dir_ || postgis_extension_
|
90
|
-
postgis_schema_ = search_path_.include?('postgis') ? 'postgis' : (search_path_.last || 'public')
|
91
|
-
if script_dir_
|
92
|
-
# Use script_dir (for postgresql < 9.1 or postgis < 2.0)
|
93
|
-
conn_.execute("SET search_path TO #{postgis_schema_}")
|
94
|
-
conn_.execute(::File.read(::File.expand_path('postgis.sql', script_dir_)))
|
95
|
-
conn_.execute(::File.read(::File.expand_path('spatial_ref_sys.sql', script_dir_)))
|
96
|
-
elsif postgis_extension_
|
97
|
-
# Use postgis_extension (for postgresql >= 9.1 and postgis >= 2.0)
|
98
|
-
postgis_extension_ = 'postgis' if postgis_extension_ == true
|
99
|
-
postgis_extension_ = postgis_extension_.to_s.split(',') unless postgis_extension_.is_a?(::Array)
|
100
|
-
postgis_extension_.each do |extname_|
|
101
|
-
if extname_ == 'postgis_topology'
|
102
|
-
raise ArgumentError, "'topology' must be in schema_search_path for postgis_topology" unless search_path_.include?('topology')
|
103
|
-
conn_.execute("CREATE EXTENSION #{extname_} SCHEMA topology")
|
104
|
-
else
|
105
|
-
conn_.execute("CREATE EXTENSION #{extname_} SCHEMA #{postgis_schema_}")
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
if has_su_
|
110
|
-
conn_.execute("GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA #{postgis_schema_} TO #{username_}")
|
111
|
-
conn_.execute("GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA #{postgis_schema_} TO #{username_}")
|
112
|
-
conn_.execute("ALTER TABLE geometry_columns OWNER TO #{username_}")
|
113
|
-
conn_.execute("ALTER TABLE spatial_ref_sys OWNER TO #{username_}")
|
114
|
-
end
|
115
|
-
end
|
150
|
+
setup_gis(config_)
|
116
151
|
|
117
152
|
# Done
|
118
153
|
::ActiveRecord::Base.establish_connection(config_)
|
@@ -47,23 +47,32 @@ class ::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
|
|
47
47
|
end
|
48
48
|
|
49
49
|
class ::ActiveRecord::Base
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
50
|
+
class << self
|
51
|
+
# ActiveRecord looks for the postgis_connection factory method in
|
52
|
+
# this class.
|
53
|
+
#
|
54
|
+
# Based on the default `postgresql_connection` definition from
|
55
|
+
# activerecord-jdbc-adapter's:
|
56
|
+
# lib/arjdbc/postgresql/connection_methods.rb
|
57
|
+
def postgis_connection(config)
|
58
|
+
begin
|
59
|
+
require 'jdbc/postgres'
|
60
|
+
::Jdbc::Postgres.load_driver(:require) if defined?(::Jdbc::Postgres.load_driver)
|
61
|
+
rescue LoadError # assuming driver.jar is on the class-path
|
62
|
+
end
|
63
|
+
require "arjdbc/postgresql"
|
64
|
+
config[:username] ||= ::Java::JavaLang::System.get_property("user.name")
|
65
|
+
config[:host] ||= "localhost"
|
66
|
+
config[:port] ||= 5432
|
67
|
+
config[:url] ||= "jdbc:postgresql://#{config[:host]}:#{config[:port]}/#{config[:database]}"
|
68
|
+
config[:url] << config[:pg_params] if config[:pg_params]
|
69
|
+
config[:driver] ||= defined?(::Jdbc::Postgres.driver_name) ? ::Jdbc::Postgres.driver_name : 'org.postgresql.Driver'
|
70
|
+
config[:adapter_class] = ::ActiveRecord::ConnectionAdapters::PostGISAdapter::MainAdapter
|
71
|
+
config[:adapter_spec] = ::ArJdbc::PostgreSQL
|
72
|
+
conn = jdbc_connection(config)
|
73
|
+
conn.execute("SET SEARCH_PATH TO #{config[:schema_search_path]}") if config[:schema_search_path]
|
74
|
+
conn
|
75
|
+
end
|
76
|
+
alias_method :jdbcpostgis_connection, :postgis_connection
|
68
77
|
end
|
69
78
|
end
|
@@ -130,8 +130,11 @@ module ActiveRecord
|
|
130
130
|
col_name_ = col_name_["column_name"]
|
131
131
|
end
|
132
132
|
|
133
|
-
SpatialColumn.new(
|
134
|
-
|
133
|
+
SpatialColumn.new(col_name_, default_, type_, notnull_ == 'f',
|
134
|
+
((type_ =~ /geometry/i ? spatial_info_[col_name_] : nil) || {}).merge({
|
135
|
+
:table_name => table_name_,
|
136
|
+
:factory_settings => @rgeo_factory_settings
|
137
|
+
}))
|
135
138
|
end
|
136
139
|
end
|
137
140
|
|
@@ -49,11 +49,11 @@ module ActiveRecord
|
|
49
49
|
FACTORY_SETTINGS_CACHE = {}
|
50
50
|
|
51
51
|
|
52
|
-
def initialize(
|
53
|
-
@factory_settings =
|
54
|
-
@table_name =
|
52
|
+
def initialize(name_, default_, sql_type_=nil, null_=true, opts_={})
|
53
|
+
@factory_settings = opts_.delete(:factory_settings)
|
54
|
+
@table_name = opts_.delete(:table_name)
|
55
55
|
@geographic = sql_type_ =~ /geography/i ? true : false
|
56
|
-
if opts_
|
56
|
+
if opts_.length > 0
|
57
57
|
# This case comes from an entry in the geometry_columns table
|
58
58
|
@geometric_type = ::RGeo::ActiveRecord.geometric_type_from_name(opts_[:type]) ||
|
59
59
|
::RGeo::Feature::Geometry
|
@@ -97,7 +97,7 @@ module ActiveRecord
|
|
97
97
|
@limit = {:no_constraints => true}
|
98
98
|
end
|
99
99
|
end
|
100
|
-
FACTORY_SETTINGS_CACHE[
|
100
|
+
FACTORY_SETTINGS_CACHE[@factory_settings.object_id] = @factory_settings
|
101
101
|
end
|
102
102
|
|
103
103
|
|
@@ -42,8 +42,13 @@ module ActiveRecord
|
|
42
42
|
|
43
43
|
module PostGISAdapter
|
44
44
|
|
45
|
+
TableDefinitionSuperclass = if defined?(ConnectionAdapters::PostgreSQLAdapter::TableDefinition)
|
46
|
+
ConnectionAdapters::PostgreSQLAdapter::TableDefinition
|
47
|
+
else
|
48
|
+
ConnectionAdapters::TableDefinition
|
49
|
+
end
|
45
50
|
|
46
|
-
class SpatialTableDefinition <
|
51
|
+
class SpatialTableDefinition < TableDefinitionSuperclass
|
47
52
|
|
48
53
|
def column(name_, type_, options_={})
|
49
54
|
if (info_ = @base.spatial_column_constructor(type_.to_sym))
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-postgis-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-02-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rgeo-activerecord
|
@@ -123,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
123
123
|
version: 1.3.1
|
124
124
|
requirements: []
|
125
125
|
rubyforge_project: virtuoso
|
126
|
-
rubygems_version: 1.8.
|
126
|
+
rubygems_version: 1.8.25
|
127
127
|
signing_key:
|
128
128
|
specification_version: 3
|
129
129
|
summary: An ActiveRecord adapter for PostGIS, based on RGeo.
|