activerecord-postgis-adapter 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,8 @@
1
+ === 0.4.1 / 2012-02-22
2
+
3
+ * Some compatibility fixes for Rails 3.2. (Reported by Ryan Williams with implementation help from Radek Paviensky.)
4
+ * Now requires rgeo-activerecord 0.4.3.
5
+
1
6
  === 0.4.0 / 2011-08-15
2
7
 
3
8
  * Various fixes for Rails 3.1 compatibility.
@@ -115,9 +115,9 @@ This adapter has the following requirements:
115
115
  * PostGIS 1.5 or later.
116
116
  * pg gem 0.11 or later.
117
117
  * \ActiveRecord 3.0.3 or later. Earlier versions will not work.
118
- Appears to be compatible with Rails 3.1rc5.
119
- * rgeo gem 0.3.2 or later.
120
- * rgeo-activerecord gem 0.4.0 or later.
118
+ Should be compatible with Rails versions through 3.2.x.
119
+ * rgeo gem 0.3.4 or later.
120
+ * rgeo-activerecord gem 0.4.3 or later.
121
121
 
122
122
  Install this adapter as a gem:
123
123
 
@@ -271,7 +271,7 @@ Contact the author at dazuma at gmail dot com.
271
271
  The PostGIS Adapter and its supporting libraries (including RGeo) are
272
272
  written by Daniel Azuma (http://www.daniel-azuma.com).
273
273
 
274
- Development of RGeo is sponsored by GeoPage, Inc. (http://www.geopage.com).
274
+ Development is supported by Pirq. (http://www.pirq.com).
275
275
 
276
276
  This adapter implementation owes some debt to the spatial_adapter plugin
277
277
  (http://github.com/fragility/spatial_adapter). Although we made some
data/Version CHANGED
@@ -1 +1 @@
1
- 0.4.0
1
+ 0.4.1
@@ -1,15 +1,15 @@
1
1
  # -----------------------------------------------------------------------------
2
- #
2
+ #
3
3
  # PostGIS adapter for ActiveRecord
4
- #
4
+ #
5
5
  # -----------------------------------------------------------------------------
6
- # Copyright 2010 Daniel Azuma
7
- #
6
+ # Copyright 2010-2012 Daniel Azuma
7
+ #
8
8
  # All rights reserved.
9
- #
9
+ #
10
10
  # Redistribution and use in source and binary forms, with or without
11
11
  # modification, are permitted provided that the following conditions are met:
12
- #
12
+ #
13
13
  # * Redistributions of source code must retain the above copyright notice,
14
14
  # this list of conditions and the following disclaimer.
15
15
  # * Redistributions in binary form must reproduce the above copyright notice,
@@ -18,7 +18,7 @@
18
18
  # * Neither the name of the copyright holder, nor the names of any other
19
19
  # contributors to this software, may be used to endorse or promote products
20
20
  # derived from this software without specific prior written permission.
21
- #
21
+ #
22
22
  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
23
  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
24
  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -42,19 +42,19 @@ require 'active_record/connection_adapters/postgresql_adapter'
42
42
  # connection adapter into ActiveRecord.
43
43
 
44
44
  module ActiveRecord
45
-
46
-
45
+
46
+
47
47
  # ActiveRecord looks for the postgis_connection factory method in
48
48
  # this class.
49
-
49
+
50
50
  class Base
51
-
52
-
51
+
52
+
53
53
  # Create a postgis connection adapter.
54
-
54
+
55
55
  def self.postgis_connection(config_)
56
56
  require 'pg'
57
-
57
+
58
58
  config_ = config_.symbolize_keys
59
59
  host_ = config_[:host]
60
60
  port_ = config_[:port] || 5432
@@ -65,30 +65,30 @@ module ActiveRecord
65
65
  else
66
66
  raise ::ArgumentError, "No database specified. Missing argument: database."
67
67
  end
68
-
68
+
69
69
  # The postgres drivers don't allow the creation of an unconnected PGconn object,
70
70
  # so just pass a nil connection object for the time being.
71
71
  ::ActiveRecord::ConnectionAdapters::PostGISAdapter::MainAdapter.new(nil, logger, [host_, port_, nil, nil, database_, username_, password_], config_)
72
72
  end
73
-
74
-
73
+
74
+
75
75
  end
76
-
77
-
76
+
77
+
78
78
  # All ActiveRecord adapters go in this namespace.
79
79
  module ConnectionAdapters
80
-
80
+
81
81
  # The PostGIS Adapter
82
82
  module PostGISAdapter
83
-
83
+
84
84
  # The name returned by the adapter_name method of this adapter.
85
85
  ADAPTER_NAME = 'PostGIS'.freeze
86
-
86
+
87
87
  end
88
-
88
+
89
89
  end
90
-
91
-
90
+
91
+
92
92
  end
93
93
 
94
94
 
@@ -1,15 +1,15 @@
1
1
  # -----------------------------------------------------------------------------
2
- #
2
+ #
3
3
  # PostGIS adapter for ActiveRecord
4
- #
4
+ #
5
5
  # -----------------------------------------------------------------------------
6
- # Copyright 2010 Daniel Azuma
7
- #
6
+ # Copyright 2010-2012 Daniel Azuma
7
+ #
8
8
  # All rights reserved.
9
- #
9
+ #
10
10
  # Redistribution and use in source and binary forms, with or without
11
11
  # modification, are permitted provided that the following conditions are met:
12
- #
12
+ #
13
13
  # * Redistributions of source code must retain the above copyright notice,
14
14
  # this list of conditions and the following disclaimer.
15
15
  # * Redistributions in binary form must reproduce the above copyright notice,
@@ -18,7 +18,7 @@
18
18
  # * Neither the name of the copyright holder, nor the names of any other
19
19
  # contributors to this software, may be used to endorse or promote products
20
20
  # derived from this software without specific prior written permission.
21
- #
21
+ #
22
22
  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
23
  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
24
  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -38,25 +38,25 @@
38
38
 
39
39
  module Arel
40
40
  module Visitors
41
-
41
+
42
42
  class PostGIS < PostgreSQL
43
-
43
+
44
44
  FUNC_MAP = {
45
45
  'st_wkttosql' => 'ST_GeomFromEWKT',
46
46
  }
47
-
47
+
48
48
  include ::RGeo::ActiveRecord::SpatialToSql
49
-
49
+
50
50
  def st_func(standard_name_)
51
51
  FUNC_MAP[standard_name_.downcase] || standard_name_
52
52
  end
53
-
53
+
54
54
  alias_method :visit_in_spatial_context, :visit
55
-
55
+
56
56
  end
57
-
57
+
58
58
  VISITORS['postgis'] = ::Arel::Visitors::PostGIS
59
-
59
+
60
60
  end
61
61
  end
62
62
 
@@ -1,15 +1,15 @@
1
1
  # -----------------------------------------------------------------------------
2
- #
2
+ #
3
3
  # Rakefile changes for PostGIS adapter
4
- #
4
+ #
5
5
  # -----------------------------------------------------------------------------
6
- # Copyright 2010 Daniel Azuma
7
- #
6
+ # Copyright 2010-2012 Daniel Azuma
7
+ #
8
8
  # All rights reserved.
9
- #
9
+ #
10
10
  # Redistribution and use in source and binary forms, with or without
11
11
  # modification, are permitted provided that the following conditions are met:
12
- #
12
+ #
13
13
  # * Redistributions of source code must retain the above copyright notice,
14
14
  # this list of conditions and the following disclaimer.
15
15
  # * Redistributions in binary form must reproduce the above copyright notice,
@@ -18,7 +18,7 @@
18
18
  # * Neither the name of the copyright holder, nor the names of any other
19
19
  # contributors to this software, may be used to endorse or promote products
20
20
  # derived from this software without specific prior written permission.
21
- #
21
+ #
22
22
  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
23
  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
24
  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -51,14 +51,14 @@ def create_database(config_)
51
51
  username_ = config_['username'] # regular user name
52
52
  su_username_ = config_['su_username'] || username_ # superuser name
53
53
  su_password_ = config_['su_password'] || config_['password'] # superuser password
54
-
54
+
55
55
  # Create the database. Optionally do so as the given superuser.
56
56
  # But make sure the database is owned by the regular user.
57
57
  ::ActiveRecord::Base.establish_connection(config_.merge('database' => 'postgres', 'schema_search_path' => 'public', 'username' => su_username_, 'password' => su_password_))
58
58
  extra_configs_ = {'encoding' => @encoding}
59
59
  extra_configs_['owner'] = username_ if has_su_
60
60
  ::ActiveRecord::Base.connection.create_database(config_['database'], config_.merge(extra_configs_))
61
-
61
+
62
62
  # Initial setup of the database: Add schemas from the search path.
63
63
  # If a superuser is given, we log in as the superuser, but we make sure
64
64
  # the schemas are owned by the regular user.
@@ -70,7 +70,7 @@ def create_database(config_)
70
70
  search_path_.each do |schema_|
71
71
  conn_.execute("CREATE SCHEMA #{schema_}#{auth_}") unless schema_.downcase == 'public'
72
72
  end
73
-
73
+
74
74
  # Define the postgis stuff, if the script_dir is provided.
75
75
  # Note: a superuser is required to run the postgis definitions.
76
76
  # If a separate superuser is provided, we need to grant privileges on
@@ -89,7 +89,7 @@ def create_database(config_)
89
89
  conn_.execute("GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA #{postgis_schema_} TO #{username_}")
90
90
  end
91
91
  end
92
-
92
+
93
93
  # Done
94
94
  ::ActiveRecord::Base.establish_connection(config_)
95
95
  rescue ::Exception => e_
@@ -1,15 +1,15 @@
1
1
  # -----------------------------------------------------------------------------
2
- #
2
+ #
3
3
  # PostGIS adapter for ActiveRecord
4
- #
4
+ #
5
5
  # -----------------------------------------------------------------------------
6
- # Copyright 2010 Daniel Azuma
7
- #
6
+ # Copyright 2010-2012 Daniel Azuma
7
+ #
8
8
  # All rights reserved.
9
- #
9
+ #
10
10
  # Redistribution and use in source and binary forms, with or without
11
11
  # modification, are permitted provided that the following conditions are met:
12
- #
12
+ #
13
13
  # * Redistributions of source code must retain the above copyright notice,
14
14
  # this list of conditions and the following disclaimer.
15
15
  # * Redistributions in binary form must reproduce the above copyright notice,
@@ -18,7 +18,7 @@
18
18
  # * Neither the name of the copyright holder, nor the names of any other
19
19
  # contributors to this software, may be used to endorse or promote products
20
20
  # derived from this software without specific prior written permission.
21
- #
21
+ #
22
22
  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
23
  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
24
  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -37,55 +37,64 @@
37
37
  # :stopdoc:
38
38
 
39
39
  module ActiveRecord
40
-
40
+
41
41
  module ConnectionAdapters
42
-
42
+
43
43
  module PostGISAdapter
44
-
45
-
44
+
45
+
46
46
  class MainAdapter < PostgreSQLAdapter
47
-
48
-
47
+
48
+
49
49
  SPATIAL_COLUMN_CONSTRUCTORS = ::RGeo::ActiveRecord::DEFAULT_SPATIAL_COLUMN_CONSTRUCTORS.merge(
50
50
  :geography => {:type => 'geometry', :geographic => true}
51
51
  )
52
-
52
+
53
53
  @@native_database_types = nil
54
-
55
-
54
+
55
+
56
+ def initialize(*args_)
57
+ super
58
+ # Rails 3.2 way of defining the visitor: do so in the constructor
59
+ if defined?(@visitor) && @visitor
60
+ @visitor = ::Arel::Visitors::PostGIS.new(self)
61
+ end
62
+ end
63
+
64
+
56
65
  def set_rgeo_factory_settings(factory_settings_)
57
66
  @rgeo_factory_settings = factory_settings_
58
67
  end
59
-
60
-
68
+
69
+
61
70
  def adapter_name
62
71
  PostGISAdapter::ADAPTER_NAME
63
72
  end
64
-
65
-
73
+
74
+
66
75
  def spatial_column_constructor(name_)
67
76
  SPATIAL_COLUMN_CONSTRUCTORS[name_]
68
77
  end
69
-
70
-
78
+
79
+
71
80
  def native_database_types
72
81
  @@native_database_types ||= super.merge(:spatial => {:name => 'geometry'})
73
82
  end
74
-
75
-
83
+
84
+
76
85
  def postgis_lib_version
77
86
  unless defined?(@postgis_lib_version)
78
87
  @postgis_lib_version = select_value("SELECT PostGIS_Lib_Version()") rescue nil
79
88
  end
80
89
  @postgis_lib_version
81
90
  end
82
-
83
-
91
+
92
+
84
93
  def srs_database_columns
85
94
  {:srtext_column => 'srtext', :proj4text_column => 'proj4text', :auth_name_column => 'auth_name', :auth_srid_column => 'auth_srid'}
86
95
  end
87
-
88
-
96
+
97
+
89
98
  def quote(value_, column_=nil)
90
99
  if ::RGeo::Feature::Geometry.check_type(value_)
91
100
  "'#{::RGeo::WKRep::WKBGenerator.new(:hex_format => true, :type_format => :ewkb, :emit_ewkb_srid => true).generate(value_)}'"
@@ -93,8 +102,8 @@ module ActiveRecord
93
102
  super
94
103
  end
95
104
  end
96
-
97
-
105
+
106
+
98
107
  def type_cast(value_, column_)
99
108
  if ::RGeo::Feature::Geometry.check_type(value_)
100
109
  ::RGeo::WKRep::WKBGenerator.new(:hex_format => true, :type_format => :ewkb, :emit_ewkb_srid => true).generate(value_)
@@ -102,29 +111,29 @@ module ActiveRecord
102
111
  super
103
112
  end
104
113
  end
105
-
106
-
114
+
115
+
107
116
  def columns(table_name_, name_=nil)
108
117
  # FULL REPLACEMENT. RE-CHECK ON NEW VERSIONS.
109
118
  # We needed to return a spatial column subclass.
110
119
  table_name_ = table_name_.to_s
111
120
  spatial_info_ = spatial_column_info(table_name_)
112
121
  column_definitions(table_name_).collect do |name_, type_, default_, notnull_|
113
- SpatialColumn.new(@rgeo_factory_settings, table_name_.to_s, name_, default_, type_,
122
+ SpatialColumn.new(@rgeo_factory_settings, table_name_, name_, default_, type_,
114
123
  notnull_ == 'f', type_ =~ /geometry/i ? spatial_info_[name_] : nil)
115
124
  end
116
125
  end
117
-
118
-
126
+
127
+
119
128
  def indexes(table_name_, name_=nil)
120
129
  # FULL REPLACEMENT. RE-CHECK ON NEW VERSIONS.
121
130
  # We needed to modify the catalog queries to pull the index type info.
122
-
131
+
123
132
  # Remove postgis from schemas
124
133
  schemas_ = schema_search_path.split(/,/)
125
134
  schemas_.delete('postgis')
126
135
  schemas_ = schemas_.map{ |p_| quote(p_) }.join(',')
127
-
136
+
128
137
  # Get index type by joining with pg_am.
129
138
  result_ = query(<<-SQL, name_)
130
139
  SELECT DISTINCT i.relname, d.indisunique, d.indkey, t.oid, am.amname
@@ -138,14 +147,14 @@ module ActiveRecord
138
147
  AND i.relam = am.oid
139
148
  ORDER BY i.relname
140
149
  SQL
141
-
150
+
142
151
  result_.map do |row_|
143
152
  index_name_ = row_[0]
144
153
  unique_ = row_[1] == 't'
145
154
  indkey_ = row_[2].split(" ")
146
155
  oid_ = row_[3]
147
156
  indtype_ = row_[4]
148
-
157
+
149
158
  columns_ = query(<<-SQL, "Columns for index #{row_[0]} on #{table_name_}").inject({}){ |h_, r_| h_[r_[0]] = [r_[1], r_[2]]; h_ }
150
159
  SELECT a.attnum, a.attname, t.typname
151
160
  FROM pg_attribute a, pg_type t
@@ -153,14 +162,14 @@ module ActiveRecord
153
162
  AND a.attnum IN (#{indkey_.join(",")})
154
163
  AND a.atttypid = t.oid
155
164
  SQL
156
-
165
+
157
166
  spatial_ = indtype_ == 'gist' && columns_.size == 1 && (columns_.values.first[1] == 'geometry' || columns_.values.first[1] == 'geography')
158
167
  column_names_ = columns_.values_at(*indkey_).compact.map{ |a_| a_[0] }
159
168
  column_names_.empty? ? nil : ::RGeo::ActiveRecord::SpatialIndexDefinition.new(table_name_, index_name_, unique_, column_names_, nil, spatial_)
160
169
  end.compact
161
170
  end
162
-
163
-
171
+
172
+
164
173
  def create_table(table_name_, options_={})
165
174
  # FULL REPLACEMENT. RE-CHECK ON NEW VERSIONS.
166
175
  # Note: we have to do a full replacement for Rails 3.0 because
@@ -175,13 +184,13 @@ module ActiveRecord
175
184
  if options_[:force] && table_exists?(table_name_)
176
185
  drop_table(table_name_, options_)
177
186
  end
178
-
187
+
179
188
  create_sql_ = "CREATE#{' TEMPORARY' if options_[:temporary]} TABLE "
180
189
  create_sql_ << "#{quote_table_name(table_name_)} ("
181
190
  create_sql_ << table_definition_.to_sql
182
191
  create_sql_ << ") #{options_[:options]}"
183
192
  execute create_sql_
184
-
193
+
185
194
  table_definition_.non_geographic_spatial_columns.each do |col_|
186
195
  type_ = col_.spatial_type.gsub('_', '').upcase
187
196
  has_z_ = col_.has_z?
@@ -193,14 +202,14 @@ module ActiveRecord
193
202
  execute("SELECT AddGeometryColumn('#{quote_string(table_name_)}', '#{quote_string(col_.name.to_s)}', #{col_.srid}, '#{quote_string(type_)}', #{dimensions_})")
194
203
  end
195
204
  end
196
-
197
-
198
- def drop_table(table_name_, options_={})
205
+
206
+
207
+ def drop_table(table_name_, *options_)
199
208
  execute("DELETE from geometry_columns where f_table_name='#{quote_string(table_name_.to_s)}'")
200
209
  super
201
210
  end
202
-
203
-
211
+
212
+
204
213
  def add_column(table_name_, column_name_, type_, options_={})
205
214
  table_name_ = table_name_.to_s
206
215
  if (info_ = spatial_column_constructor(type_.to_sym))
@@ -234,8 +243,8 @@ module ActiveRecord
234
243
  super
235
244
  end
236
245
  end
237
-
238
-
246
+
247
+
239
248
  def remove_column(table_name_, *column_names_)
240
249
  column_names_ = column_names_.flatten.map{ |n_| n_.to_s }
241
250
  spatial_info_ = spatial_column_info(table_name_)
@@ -251,8 +260,8 @@ module ActiveRecord
251
260
  super(table_name_, *remaining_column_names_)
252
261
  end
253
262
  end
254
-
255
-
263
+
264
+
256
265
  def add_index(table_name_, column_name_, options_={})
257
266
  # FULL REPLACEMENT. RE-CHECK ON NEW VERSIONS.
258
267
  # We have to fully-replace because of the gist_clause.
@@ -277,8 +286,8 @@ module ActiveRecord
277
286
  quoted_column_names_ = quoted_columns_for_index(column_names_, options_).join(", ")
278
287
  execute "CREATE #{index_type_} INDEX #{quote_column_name(index_name_)} ON #{quote_table_name(table_name_)} #{gist_clause_} (#{quoted_column_names_})"
279
288
  end
280
-
281
-
289
+
290
+
282
291
  def spatial_column_info(table_name_)
283
292
  info_ = query("SELECT * FROM geometry_columns WHERE f_table_name='#{quote_string(table_name_.to_s)}'")
284
293
  result_ = {}
@@ -300,15 +309,15 @@ module ActiveRecord
300
309
  end
301
310
  result_
302
311
  end
303
-
304
-
312
+
313
+
305
314
  end
306
-
307
-
315
+
316
+
308
317
  end
309
-
318
+
310
319
  end
311
-
320
+
312
321
  end
313
322
 
314
323
  # :startdoc: