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 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 later also supported.
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 3.x only. The upcoming version 0.6 will target Rails 4.0.
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.0
1
+ 0.5.1
@@ -35,6 +35,7 @@
35
35
 
36
36
 
37
37
  require 'rgeo/active_record'
38
+ require 'active_record/connection_adapters/postgresql_adapter'
38
39
 
39
40
  if defined?(::RUBY_ENGINE) && ::RUBY_ENGINE == 'jruby'
40
41
  require 'active_record/connection_adapters/postgis_adapter/jdbc_connection'
@@ -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_.include?('su_username') # Is there a distinct superuser?
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
- # Initial setup of the database: Add schemas from the search path.
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
- # ActiveRecord looks for the postgis_connection factory method in
51
- # this class.
52
- #
53
- # Based on the default `postgresql_connection` definition from
54
- # activerecord-jdbc-adapter's:
55
- # lib/arjdbc/postgresql/connection_methods.rb
56
- def self.postgis_connection(config)
57
- require "arjdbc/postgresql"
58
- config[:host] ||= "localhost"
59
- config[:port] ||= 5432
60
- config[:url] ||= "jdbc:postgresql://#{config[:host]}:#{config[:port]}/#{config[:database]}"
61
- config[:url] << config[:pg_params] if config[:pg_params]
62
- config[:driver] ||= "org.postgresql.Driver"
63
- config[:adapter_class] = ::ActiveRecord::ConnectionAdapters::PostGISAdapter::MainAdapter
64
- config[:adapter_spec] = ::ArJdbc::PostgreSQL
65
- conn = jdbc_connection(config)
66
- conn.execute("SET SEARCH_PATH TO #{config[:schema_search_path]}") if config[:schema_search_path]
67
- conn
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(@rgeo_factory_settings, table_name_, col_name_, default_, type_,
134
- notnull_ == 'f', type_ =~ /geometry/i ? spatial_info_[col_name_] : nil)
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
 
@@ -1,4 +1,3 @@
1
- require 'active_record/connection_adapters/postgresql_adapter'
2
1
  require 'pg'
3
2
 
4
3
  class ::ActiveRecord::Base
@@ -49,11 +49,11 @@ module ActiveRecord
49
49
  FACTORY_SETTINGS_CACHE = {}
50
50
 
51
51
 
52
- def initialize(factory_settings_, table_name_, name_, default_, sql_type_=nil, null_=true, opts_=nil)
53
- @factory_settings = factory_settings_
54
- @table_name = 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[factory_settings_.object_id] = factory_settings_
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 < ConnectionAdapters::TableDefinition
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.0
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: 2012-12-12 00:00:00.000000000 Z
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.24
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.