activerecord-spatialite-adapter 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: