activerecord-spatialite-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,12 @@
1
+ === 0.4.1 / 2012-03-17
2
+
3
+ * Some compatibility fixes for Rails 3.2.
4
+ * Geometry columns were "not null" by default. Fixed. (Patch by michael-groble.)
5
+ * Fixed exception on inserting nil values. (Patch by michael-groble.)
6
+ * No longer raises exceptions on driver versions that don't support enable_load_extension. (Patch by michael-groble.)
7
+ * Now requires rgeo-activerecord 0.4.3.
8
+ * Includes instructions for running the tests. (Thanks to vgeorge for the suggestions.)
9
+
1
10
  === 0.4.0 / 2011-08-15
2
11
 
3
12
  * Various fixes for Rails 3.1 compatibility.
@@ -97,12 +97,20 @@ write more complex queries in SQL.
97
97
  This adapter has the following requirements:
98
98
 
99
99
  * Ruby 1.8.7 or later. Ruby 1.9.2 or later preferred.
100
- * SpatiaLite 2.3 or later (2.4 recommended).
101
- * sqlite3 gem 1.3.3 or later.
100
+ * sqlite 3.7.3 or later.
101
+ * SpatiaLite 3.0 or later. Version 2.3 may work but is not officially
102
+ supported.
103
+ * sqlite3 gem 1.3.5 or later.
102
104
  * \ActiveRecord 3.0.3 or later. Earlier versions will not work.
103
- Appears to be compatible with Rails 3.1rc5.
104
- * rgeo gem 0.3.2 or later.
105
- * rgeo-activerecord gem 0.4.0 or later.
105
+ Should be compatible with Rails versions through 3.2.x.
106
+ * rgeo gem 0.3.7 or later.
107
+ * rgeo-activerecord gem 0.4.3 or later.
108
+
109
+ Note: if you are running Mac OS X, the OS-provided copy of sqlite3 may
110
+ not support extensions. You should install an alternate copy of sqlite3
111
+ (for example, using MacPorts or Homebrew) reinstall the gem using:
112
+
113
+ gem install sqlite3 -- --with-sqlite3-dir=/path/to/alternate/sqlite3
106
114
 
107
115
  Install this adapter as a gem:
108
116
 
@@ -203,11 +211,11 @@ Contact the author at dazuma at gmail dot com.
203
211
  The SpatiaLite Adapter and its supporting libraries (including RGeo) are
204
212
  written by Daniel Azuma (http://www.daniel-azuma.com).
205
213
 
206
- Development of RGeo is sponsored by GeoPage, Inc. (http://www.geopage.com).
214
+ Development is supported by Pirq. (http://www.pirq.com).
207
215
 
208
216
  === License
209
217
 
210
- Copyright 2010-2011 Daniel Azuma
218
+ Copyright 2010-2012 Daniel Azuma
211
219
 
212
220
  All rights reserved.
213
221
 
data/Version CHANGED
@@ -1 +1 @@
1
- 0.4.0
1
+ 0.4.1
@@ -1,15 +1,15 @@
1
1
  # -----------------------------------------------------------------------------
2
- #
2
+ #
3
3
  # SpatiaLite adapter for ActiveRecord
4
- #
4
+ #
5
5
  # -----------------------------------------------------------------------------
6
6
  # Copyright 2010 Daniel Azuma
7
- #
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,16 +42,16 @@ require 'active_record/connection_adapters/sqlite3_adapter'
42
42
  # connection adapter into ActiveRecord.
43
43
 
44
44
  module ActiveRecord
45
-
46
-
45
+
46
+
47
47
  # ActiveRecord looks for the spatialite_connection factory method in
48
48
  # this class.
49
-
49
+
50
50
  class Base
51
-
52
-
51
+
52
+
53
53
  # Create a spatialite connection adapter.
54
-
54
+
55
55
  def self.spatialite_connection(config_)
56
56
  unless 'spatialite' == config_[:adapter]
57
57
  raise ::ArgumentError, 'adapter name should be "spatialite"'
@@ -59,20 +59,17 @@ module ActiveRecord
59
59
  unless config_[:database]
60
60
  raise ::ArgumentError, "No database file specified. Missing argument: database"
61
61
  end
62
-
62
+
63
63
  # Allow database path relative to Rails.root, but only if
64
64
  # the database path is not the special path that tells
65
65
  # Sqlite to build a database only in memory.
66
66
  if defined?(::Rails.root) && ':memory:' != config_[:database]
67
67
  config_[:database] = ::File.expand_path(config_[:database], ::Rails.root)
68
68
  end
69
-
70
- unless self.class.const_defined?(:SQLite3)
71
- require_library_or_gem('sqlite3')
72
- end
69
+
73
70
  db_ = ::SQLite3::Database.new(config_[:database], :results_as_hash => true)
74
71
  db_.busy_timeout(config_[:timeout]) unless config_[:timeout].nil?
75
-
72
+
76
73
  # Load SpatiaLite
77
74
  path_ = config_[:libspatialite]
78
75
  if path_ && (!::File.file?(path_) || !::File.readable?(path_))
@@ -92,30 +89,32 @@ module ActiveRecord
92
89
  unless path_
93
90
  raise 'Cannot find libspatialite in the usual places. Please provide the path in the "libspatialite" config parameter.'
94
91
  end
95
- db_.enable_load_extension(1)
96
- db_.load_extension(path_)
97
-
92
+ if db_.respond_to?(:enable_load_extension)
93
+ db_.enable_load_extension(1)
94
+ db_.load_extension(path_)
95
+ end
96
+
98
97
  ::ActiveRecord::ConnectionAdapters::SpatiaLiteAdapter::MainAdapter.new(db_, logger, config_)
99
98
  end
100
-
101
-
99
+
100
+
102
101
  end
103
-
104
-
102
+
103
+
105
104
  # All ActiveRecord adapters go in this namespace.
106
105
  module ConnectionAdapters
107
-
106
+
108
107
  # The SpatiaLite Adapter
109
108
  module SpatiaLiteAdapter
110
-
109
+
111
110
  # The name returned by the adapter_name method of this adapter.
112
111
  ADAPTER_NAME = 'SpatiaLite'.freeze
113
-
112
+
114
113
  end
115
-
114
+
116
115
  end
117
-
118
-
116
+
117
+
119
118
  end
120
119
 
121
120
 
@@ -1,15 +1,15 @@
1
1
  # -----------------------------------------------------------------------------
2
- #
2
+ #
3
3
  # SpatiaLite adapter for ActiveRecord
4
- #
4
+ #
5
5
  # -----------------------------------------------------------------------------
6
6
  # Copyright 2010 Daniel Azuma
7
- #
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,23 +38,23 @@
38
38
 
39
39
  module Arel
40
40
  module Visitors
41
-
41
+
42
42
  class SpatiaLite < SQLite
43
-
43
+
44
44
  FUNC_MAP = {
45
45
  'st_wkttosql' => 'GeomFromText',
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
  end
55
-
55
+
56
56
  VISITORS['spatialite'] = ::Arel::Visitors::SpatiaLite
57
-
57
+
58
58
  end
59
59
  end
60
60
 
@@ -1,15 +1,15 @@
1
1
  # -----------------------------------------------------------------------------
2
- #
2
+ #
3
3
  # Rakefile changes for SpatiaLite adapter
4
- #
4
+ #
5
5
  # -----------------------------------------------------------------------------
6
6
  # Copyright 2010 Daniel Azuma
7
- #
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
@@ -1,15 +1,15 @@
1
1
  # -----------------------------------------------------------------------------
2
- #
2
+ #
3
3
  # SpatiaLite adapter for ActiveRecord
4
- #
4
+ #
5
5
  # -----------------------------------------------------------------------------
6
6
  # Copyright 2010 Daniel Azuma
7
- #
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,48 +37,57 @@
37
37
  # :stopdoc:
38
38
 
39
39
  module ActiveRecord
40
-
40
+
41
41
  module ConnectionAdapters
42
-
42
+
43
43
  module SpatiaLiteAdapter
44
-
45
-
44
+
45
+
46
46
  class MainAdapter < SQLite3Adapter
47
-
48
-
47
+
48
+
49
49
  @@native_database_types = nil
50
-
51
-
50
+
51
+
52
+ def initialize(*args_)
53
+ super
54
+ # Rails 3.2 way of defining the visitor: do so in the constructor
55
+ if defined?(@visitor) && @visitor
56
+ @visitor = ::Arel::Visitors::SpatiaLite.new(self)
57
+ end
58
+ end
59
+
60
+
52
61
  def set_rgeo_factory_settings(factory_settings_)
53
62
  @rgeo_factory_settings = factory_settings_
54
63
  end
55
-
56
-
64
+
65
+
57
66
  def adapter_name
58
67
  SpatiaLiteAdapter::ADAPTER_NAME
59
68
  end
60
-
61
-
69
+
70
+
62
71
  def spatial_column_constructor(name_)
63
72
  ::RGeo::ActiveRecord::DEFAULT_SPATIAL_COLUMN_CONSTRUCTORS[name_]
64
73
  end
65
-
66
-
74
+
75
+
67
76
  def native_database_types
68
77
  @@native_database_types ||= super.merge(:spatial => {:name => 'geometry'})
69
78
  end
70
-
71
-
79
+
80
+
72
81
  def spatialite_version
73
82
  @spatialite_version ||= SQLiteAdapter::Version.new(select_value('SELECT spatialite_version()'))
74
83
  end
75
-
76
-
84
+
85
+
77
86
  def srs_database_columns
78
87
  {:name_column => 'ref_sys_name', :proj4text_column => 'proj4text', :auth_name_column => 'auth_name', :auth_srid_column => 'auth_srid'}
79
88
  end
80
-
81
-
89
+
90
+
82
91
  def quote(value_, column_=nil)
83
92
  if ::RGeo::Feature::Geometry.check_type(value_)
84
93
  "GeomFromWKB(X'#{::RGeo::WKRep::WKBGenerator.new(:hex_format => true).generate(value_)}', #{value_.srid})"
@@ -86,8 +95,8 @@ module ActiveRecord
86
95
  super
87
96
  end
88
97
  end
89
-
90
-
98
+
99
+
91
100
  def substitute_at(column_, index_)
92
101
  if column_.spatial?
93
102
  ::Arel.sql('GeomFromText(?,?)')
@@ -95,8 +104,8 @@ module ActiveRecord
95
104
  super
96
105
  end
97
106
  end
98
-
99
-
107
+
108
+
100
109
  def type_cast(value_, column_)
101
110
  if column_.spatial? && ::RGeo::Feature::Geometry.check_type(value_)
102
111
  ::RGeo::WKRep::WKTGenerator.new(:convert_case => :upper).generate(value_)
@@ -104,22 +113,22 @@ module ActiveRecord
104
113
  super
105
114
  end
106
115
  end
107
-
108
-
116
+
117
+
109
118
  def exec_query(sql_, name_=nil, binds_=[])
110
119
  real_binds_ = []
111
120
  binds_.each do |bind_|
112
121
  if bind_[0].spatial?
113
122
  real_binds_ << bind_
114
- real_binds_ << [bind_[0], bind_[1].srid]
123
+ real_binds_ << [bind_[0], bind_[1] ? bind_[1].srid : nil]
115
124
  else
116
125
  real_binds_ << bind_
117
126
  end
118
127
  end
119
128
  super(sql_, name_, real_binds_)
120
129
  end
121
-
122
-
130
+
131
+
123
132
  def columns(table_name_, name_=nil) #:nodoc:
124
133
  spatial_info_ = spatial_column_info(table_name_)
125
134
  table_structure(table_name_).map do |field_|
@@ -132,8 +141,8 @@ module ActiveRecord
132
141
  col_
133
142
  end
134
143
  end
135
-
136
-
144
+
145
+
137
146
  def indexes(table_name_, name_=nil)
138
147
  results_ = super.map do |index_|
139
148
  ::RGeo::ActiveRecord::SpatialIndexDefinition.new(index_.table, index_.name, index_.unique, index_.columns, index_.lengths)
@@ -145,8 +154,8 @@ module ActiveRecord
145
154
  ::RGeo::ActiveRecord::SpatialIndexDefinition.new(table_name_, n_, false, [col_name_], [], true)
146
155
  end
147
156
  end
148
-
149
-
157
+
158
+
150
159
  def create_table(table_name_, options_={})
151
160
  table_name_ = table_name_.to_s
152
161
  table_definition_ = SpatialTableDefinition.new(self)
@@ -155,40 +164,42 @@ module ActiveRecord
155
164
  if options_[:force] && table_exists?(table_name_)
156
165
  drop_table(table_name_, options_)
157
166
  end
158
-
167
+
159
168
  create_sql_ = "CREATE#{' TEMPORARY' if options_[:temporary]} TABLE "
160
169
  create_sql_ << "#{quote_table_name(table_name_)} ("
161
170
  create_sql_ << table_definition_.to_sql
162
171
  create_sql_ << ") #{options_[:options]}"
163
172
  execute create_sql_
164
-
173
+
165
174
  table_definition_.spatial_columns.each do |col_|
166
- execute("SELECT AddGeometryColumn('#{quote_string(table_name_)}', '#{quote_string(col_.name.to_s)}', #{col_.srid}, '#{quote_string(col_.spatial_type.gsub('_','').upcase)}', 'XY', #{col_.null ? 0 : 1})")
175
+ null_ = col_.null.nil? ? true : col_.null
176
+ execute("SELECT AddGeometryColumn('#{quote_string(table_name_)}', '#{quote_string(col_.name.to_s)}', #{col_.srid}, '#{quote_string(col_.spatial_type.gsub('_','').upcase)}', 'XY', #{null_ ? 0 : 1})")
167
177
  end
168
178
  end
169
-
170
-
171
- def drop_table(table_name_, options_={})
179
+
180
+
181
+ def drop_table(table_name_, *options_)
172
182
  indexes(table_name_).each do |index_|
173
183
  remove_index(table_name_, :spatial => true, :column => index_.columns[0]) if index_.spatial
174
184
  end
175
185
  execute("DELETE from geometry_columns where f_table_name='#{quote_string(table_name_.to_s)}'")
176
186
  super
177
187
  end
178
-
179
-
188
+
189
+
180
190
  def add_column(table_name_, column_name_, type_, options_={})
181
191
  if (info_ = spatial_column_constructor(type_.to_sym))
182
192
  limit_ = options_[:limit]
183
193
  options_.merge!(limit_) if limit_.is_a?(::Hash)
184
194
  type_ = (options_[:type] || info_[:type] || type_).to_s.gsub('_', '').upcase
185
- execute("SELECT AddGeometryColumn('#{quote_string(table_name_.to_s)}', '#{quote_string(column_name_.to_s)}', #{options_[:srid].to_i}, '#{quote_string(type_.to_s)}', 'XY', #{options_[:null] == false ? 0 : 1})")
195
+ null_ = options_[:null].nil? ? true : options_[:null]
196
+ execute("SELECT AddGeometryColumn('#{quote_string(table_name_.to_s)}', '#{quote_string(column_name_.to_s)}', #{options_[:srid].to_i}, '#{quote_string(type_.to_s)}', 'XY', #{null_ ? 0 : 1})")
186
197
  else
187
198
  super
188
199
  end
189
200
  end
190
-
191
-
201
+
202
+
192
203
  def add_index(table_name_, column_name_, options_={})
193
204
  if options_[:spatial]
194
205
  column_name_ = column_name_.first if column_name_.kind_of?(::Array) && column_name_.size == 1
@@ -207,8 +218,8 @@ module ActiveRecord
207
218
  super
208
219
  end
209
220
  end
210
-
211
-
221
+
222
+
212
223
  def remove_index(table_name_, options_={})
213
224
  if options_[:spatial]
214
225
  table_name_ = table_name_.to_s
@@ -242,8 +253,8 @@ module ActiveRecord
242
253
  super
243
254
  end
244
255
  end
245
-
246
-
256
+
257
+
247
258
  def spatial_column_info(table_name_)
248
259
  info_ = execute("SELECT * FROM geometry_columns WHERE f_table_name='#{quote_string(table_name_.to_s)}'")
249
260
  result_ = {}
@@ -258,15 +269,15 @@ module ActiveRecord
258
269
  end
259
270
  result_
260
271
  end
261
-
262
-
272
+
273
+
263
274
  end
264
-
265
-
275
+
276
+
266
277
  end
267
-
278
+
268
279
  end
269
-
280
+
270
281
  end
271
282
 
272
283
  # :startdoc: